From d6768f15a1696bbc0b0680f21052a8f8146ee356 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Fri, 24 Nov 2017 22:20:54 +0100 Subject: [PATCH 01/16] Pump version to 0.76 --- hassio/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hassio/const.py b/hassio/const.py index 56c7a0110..56a102f66 100644 --- a/hassio/const.py +++ b/hassio/const.py @@ -2,7 +2,7 @@ from pathlib import Path from ipaddress import ip_network -HASSIO_VERSION = '0.75' +HASSIO_VERSION = '0.76' URL_HASSIO_VERSION = ('https://raw.githubusercontent.com/home-assistant/' 'hassio/{}/version.json') From 747810b72962715565517e28e4f50ea917ac7a4c Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Sat, 25 Nov 2017 09:50:23 +0100 Subject: [PATCH 02/16] Update Home-Assistant to 0.58.1 --- version.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.json b/version.json index 428c41403..0c1063631 100644 --- a/version.json +++ b/version.json @@ -1,6 +1,6 @@ { "hassio": "0.75", - "homeassistant": "0.57.3", + "homeassistant": "0.58.1", "resinos": "1.1", "resinhup": "0.3", "generic": "0.3", From 8f94b4d63f5f474ee07b6d1608a48c9f9a6d94f0 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Thu, 30 Nov 2017 20:23:20 +0100 Subject: [PATCH 03/16] Print error on invalid json (#263) --- hassio/api/util.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hassio/api/util.py b/hassio/api/util.py index b04451a1c..78c2efd4c 100644 --- a/hassio/api/util.py +++ b/hassio/api/util.py @@ -17,10 +17,12 @@ _LOGGER = logging.getLogger(__name__) def json_loads(data): """Extract json from string with support for '' and None.""" + if not data: + return {} try: return json.loads(data) except json.JSONDecodeError: - return {} + raise RuntimeError("Invalid json") def api_process(method): From 19f413796d6e6f7f2081ee9b8ac3c5e691b30e01 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Mon, 4 Dec 2017 10:49:15 +0100 Subject: [PATCH 04/16] Update Home-Assistant to version 0.59 --- version.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.json b/version.json index 0c1063631..71fe82fef 100644 --- a/version.json +++ b/version.json @@ -1,6 +1,6 @@ { "hassio": "0.75", - "homeassistant": "0.58.1", + "homeassistant": "0.59", "resinos": "1.1", "resinhup": "0.3", "generic": "0.3", From 86faf32709db68e22989017c646659fd0722345d Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Mon, 4 Dec 2017 18:14:53 +0100 Subject: [PATCH 05/16] Update Home-Assistant to 0.59.1 --- version.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.json b/version.json index 71fe82fef..99b500897 100644 --- a/version.json +++ b/version.json @@ -1,6 +1,6 @@ { "hassio": "0.75", - "homeassistant": "0.59", + "homeassistant": "0.59.1", "resinos": "1.1", "resinhup": "0.3", "generic": "0.3", From 5ce6abdbb6d38123cba59673a839212df0940f52 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Wed, 6 Dec 2017 16:30:38 +0100 Subject: [PATCH 06/16] Update Home-Assistant to 0.59.2 --- version.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.json b/version.json index 99b500897..49d940da6 100644 --- a/version.json +++ b/version.json @@ -1,6 +1,6 @@ { "hassio": "0.75", - "homeassistant": "0.59.1", + "homeassistant": "0.59.2", "resinos": "1.1", "resinhup": "0.3", "generic": "0.3", From e5e28747d4107017acf44521dd6e1344c8e28ffb Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Sun, 10 Dec 2017 22:13:40 +0100 Subject: [PATCH 07/16] Cleanup dockerfile --- Dockerfile | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/Dockerfile b/Dockerfile index 075eaf8fd..dd9592d1b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,21 +1,16 @@ ARG BUILD_FROM FROM $BUILD_FROM -# add env +# Add env ENV LANG C.UTF-8 -# setup base -RUN apk add --no-cache python3 python3-dev \ - libressl libressl-dev \ - libffi libffi-dev \ - musl musl-dev \ - gcc libstdc++ \ - git socat \ - && pip3 install --no-cache-dir --upgrade pip \ - && pip3 install --no-cache-dir --upgrade cryptography jwcrypto \ - && apk del python3-dev libressl-dev libffi-dev musl-dev gcc +# Setup base +RUN apk add --no-cache \ + python3 \ + git \ + socat -# install HassIO +# Install HassIO COPY . /usr/src/hassio RUN pip3 install --no-cache-dir /usr/src/hassio \ && rm -rf /usr/src/hassio From 664334f1ad4505f8c9324df9d535234bd441d04b Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Sun, 10 Dec 2017 22:16:22 +0100 Subject: [PATCH 08/16] Move setup to python 3.6 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 9625b45af..f723f5a03 100644 --- a/setup.py +++ b/setup.py @@ -24,7 +24,7 @@ setup( 'Topic :: Scientific/Engineering :: Atmospheric Science', 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', - 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', ], keywords=['docker', 'home-assistant', 'api'], zip_safe=False, From 6a5bd5a014bfd6d032fcba0c63da03d318e22f38 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Sun, 10 Dec 2017 23:10:25 +0100 Subject: [PATCH 09/16] Disable AppArmor/SecComp (#266) Disable AppArmor --- hassio/dock/addon.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/hassio/dock/addon.py b/hassio/dock/addon.py index 8b95bb63f..881712d29 100644 --- a/hassio/dock/addon.py +++ b/hassio/dock/addon.py @@ -95,6 +95,17 @@ class DockerAddon(DockerInterface): if host_port } + @property + def security_opt(self): + """Controlling security opt.""" + privileged = self.addon.privileged or [] + + # Disable AppArmor sinse it make troubles wit SYS_ADMIN + if 'SYS_ADMIN' in privileged: + return [ + "apparmor:unconfined", + ] + @property def tmpfs(self): """Return tmpfs for docker add-on.""" @@ -199,6 +210,7 @@ class DockerAddon(DockerInterface): extra_hosts=self.network_mapping, devices=self.devices, cap_add=self.addon.privileged, + security_opt=self.security_opt, environment=self.environment, volumes=self.volumes, tmpfs=self.tmpfs From ece6c644cf8ba301ad9c64257da27bcd3c568dc9 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Sun, 10 Dec 2017 23:29:51 +0100 Subject: [PATCH 10/16] IPC (#267) * Update API.md * Update const.py * Update addon.py * Update validate.py * Update addon.py * Update addons.py * fix lint --- API.md | 3 +++ hassio/addons/addon.py | 7 ++++++- hassio/addons/validate.py | 3 ++- hassio/api/addons.py | 6 +++++- hassio/const.py | 1 + hassio/dock/addon.py | 7 +++++++ 6 files changed, 24 insertions(+), 3 deletions(-) diff --git a/API.md b/API.md index db9e103ec..dbd596b77 100644 --- a/API.md +++ b/API.md @@ -357,6 +357,8 @@ Get all available addons. "audio": "bool", "gpio": "bool", "stdin": "bool", + "host_ipc": "bool", + "host_network": "bool", "hassio_api": "bool", "homeassistant_api": "bool" } @@ -392,6 +394,7 @@ Get all available addons. "options": "{}", "network": "{}|null", "host_network": "bool", + "host_ipc": "bool", "privileged": ["NET_ADMIN", "SYS_ADMIN"], "devices": ["/dev/xy"], "logo": "bool", diff --git a/hassio/addons/addon.py b/hassio/addons/addon.py index d232c8ddb..0e0695d18 100644 --- a/hassio/addons/addon.py +++ b/hassio/addons/addon.py @@ -21,7 +21,7 @@ from ..const import ( STATE_STARTED, STATE_STOPPED, STATE_NONE, ATTR_USER, ATTR_SYSTEM, ATTR_STATE, ATTR_TIMEOUT, ATTR_AUTO_UPDATE, ATTR_NETWORK, ATTR_WEBUI, ATTR_HASSIO_API, ATTR_AUDIO, ATTR_AUDIO_OUTPUT, ATTR_AUDIO_INPUT, - ATTR_GPIO, ATTR_HOMEASSISTANT_API, ATTR_STDIN, ATTR_LEGACY) + ATTR_GPIO, ATTR_HOMEASSISTANT_API, ATTR_STDIN, ATTR_LEGACY, ATTR_HOST_IPC) from .util import check_installed from ..dock.addon import DockerAddon from ..tools import write_json_file, read_json_file @@ -243,6 +243,11 @@ class Addon(object): """Return True if addon run on host network.""" return self._mesh[ATTR_HOST_NETWORK] + @property + def host_ipc(self): + """Return True if addon run on host IPC namespace.""" + return self._mesh[ATTR_HOST_IPC] + @property def devices(self): """Return devices of addon.""" diff --git a/hassio/addons/validate.py b/hassio/addons/validate.py index 4d82b04e9..d24c14535 100644 --- a/hassio/addons/validate.py +++ b/hassio/addons/validate.py @@ -14,7 +14,7 @@ from ..const import ( ARCH_AARCH64, ARCH_AMD64, ARCH_I386, ATTR_TMPFS, ATTR_PRIVILEGED, ATTR_USER, ATTR_STATE, ATTR_SYSTEM, STATE_STARTED, STATE_STOPPED, ATTR_LOCATON, ATTR_REPOSITORY, ATTR_TIMEOUT, ATTR_NETWORK, ATTR_UUID, - ATTR_AUTO_UPDATE, ATTR_WEBUI, ATTR_AUDIO, ATTR_AUDIO_INPUT, + ATTR_AUTO_UPDATE, ATTR_WEBUI, ATTR_AUDIO, ATTR_AUDIO_INPUT, ATTR_HOST_IPC, ATTR_AUDIO_OUTPUT, ATTR_HASSIO_API, ATTR_BUILD_FROM, ATTR_SQUASH, ATTR_ARGS, ATTR_GPIO, ATTR_HOMEASSISTANT_API, ATTR_STDIN, ATTR_LEGACY) from ..validate import NETWORK_PORT, DOCKER_PORTS, ALSA_CHANNEL @@ -92,6 +92,7 @@ SCHEMA_ADDON_CONFIG = vol.Schema({ vol.Optional(ATTR_WEBUI): vol.Match(r"^(?:https?|\[PROTO:\w+\]):\/\/\[HOST\]:\[PORT:\d+\].*$"), vol.Optional(ATTR_HOST_NETWORK, default=False): vol.Boolean(), + vol.Optional(ATTR_HOST_IPC, default=False): vol.Boolean(), vol.Optional(ATTR_DEVICES): [vol.Match(r"^(.*):(.*):([rwm]{1,3})$")], vol.Optional(ATTR_TMPFS): vol.Match(r"^size=(\d)*[kmg](,uid=\d{1,4})?(,rw)?$"), diff --git a/hassio/api/addons.py b/hassio/api/addons.py index dd8aad01c..0c158b748 100644 --- a/hassio/api/addons.py +++ b/hassio/api/addons.py @@ -13,7 +13,8 @@ from ..const import ( ATTR_SOURCE, ATTR_REPOSITORIES, ATTR_ADDONS, ATTR_ARCH, ATTR_MAINTAINER, ATTR_INSTALLED, ATTR_LOGO, ATTR_WEBUI, ATTR_DEVICES, ATTR_PRIVILEGED, ATTR_AUDIO, ATTR_AUDIO_INPUT, ATTR_AUDIO_OUTPUT, ATTR_HASSIO_API, - ATTR_GPIO, ATTR_HOMEASSISTANT_API, ATTR_STDIN, BOOT_AUTO, BOOT_MANUAL, + ATTR_GPIO, ATTR_HOMEASSISTANT_API, ATTR_STDIN, ATTR_HOST_IPC, + BOOT_AUTO, BOOT_MANUAL, CONTENT_TYPE_PNG, CONTENT_TYPE_BINARY) from ..validate import DOCKER_PORTS @@ -75,6 +76,8 @@ class APIAddons(object): ATTR_REPOSITORY: addon.repository, ATTR_BUILD: addon.need_build, ATTR_PRIVILEGED: addon.privileged, + ATTR_HOST_NETWORK: addon.host_network, + ATTR_HOST_IPC: addon.host_ipc, ATTR_DEVICES: self._pretty_devices(addon), ATTR_URL: addon.url, ATTR_LOGO: addon.with_logo, @@ -126,6 +129,7 @@ class APIAddons(object): ATTR_BUILD: addon.need_build, ATTR_NETWORK: addon.ports, ATTR_HOST_NETWORK: addon.host_network, + ATTR_HOST_IPC: addon.host_ipc, ATTR_PRIVILEGED: addon.privileged, ATTR_DEVICES: self._pretty_devices(addon), ATTR_LOGO: addon.with_logo, diff --git a/hassio/const.py b/hassio/const.py index 56a102f66..0cbb4aff7 100644 --- a/hassio/const.py +++ b/hassio/const.py @@ -100,6 +100,7 @@ ATTR_BUILD = 'build' ATTR_DEVICES = 'devices' ATTR_ENVIRONMENT = 'environment' ATTR_HOST_NETWORK = 'host_network' +ATTR_HOST_IPC = 'host_ipc' ATTR_NETWORK = 'network' ATTR_TMPFS = 'tmpfs' ATTR_PRIVILEGED = 'privileged' diff --git a/hassio/dock/addon.py b/hassio/dock/addon.py index 881712d29..453f11cae 100644 --- a/hassio/dock/addon.py +++ b/hassio/dock/addon.py @@ -45,6 +45,12 @@ class DockerAddon(DockerInterface): """Return name of docker container.""" return "addon_{}".format(self.addon.slug) + @property + def ipc(self): + """Return the IPC namespace.""" + if self.addon.host_ipc: + return 'host' + @property def hostname(self): """Return slug/id of addon.""" @@ -204,6 +210,7 @@ class DockerAddon(DockerInterface): hostname=self.hostname, detach=True, init=True, + ipc_mode=self.ipc, stdin_open=self.addon.with_stdin, network_mode=self.network_mode, ports=self.ports, From 1e3868bb70ff9baff3ec95a27140e5a98ec1cb82 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Sun, 10 Dec 2017 23:45:30 +0100 Subject: [PATCH 11/16] Add support for changelog (#271) --- API.md | 3 +++ hassio/addons/addon.py | 10 ++++++++++ hassio/api/__init__.py | 2 ++ hassio/api/addons.py | 17 ++++++++++++++--- hassio/const.py | 2 ++ 5 files changed, 31 insertions(+), 3 deletions(-) diff --git a/API.md b/API.md index dbd596b77..95e53dc64 100644 --- a/API.md +++ b/API.md @@ -398,6 +398,7 @@ Get all available addons. "privileged": ["NET_ADMIN", "SYS_ADMIN"], "devices": ["/dev/xy"], "logo": "bool", + "changelog": "bool", "hassio_api": "bool", "homeassistant_api": "bool", "stdin": "bool", @@ -411,6 +412,8 @@ Get all available addons. - GET `/addons/{addon}/logo` +- GET `/addons/{addon}/changelog` + - POST `/addons/{addon}/options` ```json diff --git a/hassio/addons/addon.py b/hassio/addons/addon.py index 0e0695d18..e24653df9 100644 --- a/hassio/addons/addon.py +++ b/hassio/addons/addon.py @@ -348,6 +348,11 @@ class Addon(object): """Return True if a logo exists.""" return self.path_logo.exists() + @property + def with_changelog(self): + """Return True if a changelog exists.""" + return self.path_changelog.exists() + @property def supported_arch(self): """Return list of supported arch.""" @@ -407,6 +412,11 @@ class Addon(object): """Return path to addon logo.""" return Path(self.path_location, 'logo.png') + @property + def path_changelog(self): + """Return path to addon changelog.""" + return Path(self.path_location, 'CHANGELOG.md') + def write_options(self): """Return True if addon options is written to data.""" schema = self.schema diff --git a/hassio/api/__init__.py b/hassio/api/__init__.py index fd906336d..269fbfd6f 100644 --- a/hassio/api/__init__.py +++ b/hassio/api/__init__.py @@ -104,6 +104,8 @@ class RestAPI(object): '/addons/{addon}/rebuild', api_addons.rebuild) self.webapp.router.add_get('/addons/{addon}/logs', api_addons.logs) self.webapp.router.add_get('/addons/{addon}/logo', api_addons.logo) + self.webapp.router.add_get( + '/addons/{addon}/changelog', api_addons.changelog) self.webapp.router.add_post('/addons/{addon}/stdin', api_addons.stdin) def register_security(self): diff --git a/hassio/api/addons.py b/hassio/api/addons.py index 0c158b748..b6d6408af 100644 --- a/hassio/api/addons.py +++ b/hassio/api/addons.py @@ -13,9 +13,9 @@ from ..const import ( ATTR_SOURCE, ATTR_REPOSITORIES, ATTR_ADDONS, ATTR_ARCH, ATTR_MAINTAINER, ATTR_INSTALLED, ATTR_LOGO, ATTR_WEBUI, ATTR_DEVICES, ATTR_PRIVILEGED, ATTR_AUDIO, ATTR_AUDIO_INPUT, ATTR_AUDIO_OUTPUT, ATTR_HASSIO_API, - ATTR_GPIO, ATTR_HOMEASSISTANT_API, ATTR_STDIN, ATTR_HOST_IPC, - BOOT_AUTO, BOOT_MANUAL, - CONTENT_TYPE_PNG, CONTENT_TYPE_BINARY) + ATTR_GPIO, ATTR_HOMEASSISTANT_API, ATTR_STDIN, BOOT_AUTO, BOOT_MANUAL, + ATTR_CHANGELOG, ATTR_HOST_IPC, + CONTENT_TYPE_PNG, CONTENT_TYPE_BINARY, CONTENT_TYPE_TEXT) from ..validate import DOCKER_PORTS _LOGGER = logging.getLogger(__name__) @@ -133,6 +133,7 @@ class APIAddons(object): ATTR_PRIVILEGED: addon.privileged, ATTR_DEVICES: self._pretty_devices(addon), ATTR_LOGO: addon.with_logo, + ATTR_CHANGELOG: addon.with_changelog, ATTR_WEBUI: addon.webui, ATTR_STDIN: addon.with_stdin, ATTR_HASSIO_API: addon.access_hassio_api, @@ -242,6 +243,16 @@ class APIAddons(object): with addon.path_logo.open('rb') as png: return png.read() + @api_process_raw(CONTENT_TYPE_TEXT) + async def changelog(self, request): + """Return changelog from addon.""" + addon = self._extract_addon(request, check_installed=False) + if not addon.with_changelog: + raise RuntimeError("No changelog found!") + + with addon.path_changelog.open('r') as changelog: + return changelog.read() + @api_process async def stdin(self, request): """Write to stdin of addon.""" diff --git a/hassio/const.py b/hassio/const.py index 0cbb4aff7..ba9843525 100644 --- a/hassio/const.py +++ b/hassio/const.py @@ -50,9 +50,11 @@ RESULT_OK = 'ok' CONTENT_TYPE_BINARY = 'application/octet-stream' CONTENT_TYPE_PNG = 'image/png' CONTENT_TYPE_JSON = 'application/json' +CONTENT_TYPE_TEXT = 'text/plain' HEADER_HA_ACCESS = 'x-ha-access' ATTR_WATCHDOG = 'watchdog' +ATTR_CHANGELOG = 'changelog' ATTR_DATE = 'date' ATTR_ARCH = 'arch' ATTR_HOSTNAME = 'hostname' From fd41bda828d459991791cc35f7232f0c619bbe96 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Mon, 11 Dec 2017 22:40:02 +0100 Subject: [PATCH 12/16] Cleanup some API stuff (#272) * Update API.md * Update addons.py --- API.md | 11 +---------- hassio/api/addons.py | 9 --------- 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/API.md b/API.md index 95e53dc64..cfd65298e 100644 --- a/API.md +++ b/API.md @@ -350,17 +350,8 @@ Get all available addons. "installed": "none|INSTALL_VERSION", "detached": "bool", "build": "bool", - "privileged": ["NET_ADMIN", "SYS_ADMIN"], - "devices": ["/dev/xy"], "url": "null|url", - "logo": "bool", - "audio": "bool", - "gpio": "bool", - "stdin": "bool", - "host_ipc": "bool", - "host_network": "bool", - "hassio_api": "bool", - "homeassistant_api": "bool" + "logo": "bool" } ], "repositories": [ diff --git a/hassio/api/addons.py b/hassio/api/addons.py index b6d6408af..0e9268168 100644 --- a/hassio/api/addons.py +++ b/hassio/api/addons.py @@ -75,17 +75,8 @@ class APIAddons(object): ATTR_DETACHED: addon.is_detached, ATTR_REPOSITORY: addon.repository, ATTR_BUILD: addon.need_build, - ATTR_PRIVILEGED: addon.privileged, - ATTR_HOST_NETWORK: addon.host_network, - ATTR_HOST_IPC: addon.host_ipc, - ATTR_DEVICES: self._pretty_devices(addon), ATTR_URL: addon.url, ATTR_LOGO: addon.with_logo, - ATTR_STDIN: addon.with_stdin, - ATTR_HASSIO_API: addon.access_hassio_api, - ATTR_HOMEASSISTANT_API: addon.access_homeassistant_api, - ATTR_AUDIO: addon.with_audio, - ATTR_GPIO: addon.with_gpio, }) data_repositories = [] From 26d8dc0ec646309a865cc6a5b64a6809d9e13585 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Tue, 12 Dec 2017 09:10:39 +0100 Subject: [PATCH 13/16] Add support for host dbus system (#274) --- API.md | 1 + hassio/addons/addon.py | 8 +++++++- hassio/addons/validate.py | 4 +++- hassio/api/addons.py | 3 ++- hassio/const.py | 1 + hassio/dock/addon.py | 27 +++++++++++++++++---------- 6 files changed, 31 insertions(+), 13 deletions(-) diff --git a/API.md b/API.md index cfd65298e..835138be9 100644 --- a/API.md +++ b/API.md @@ -386,6 +386,7 @@ Get all available addons. "network": "{}|null", "host_network": "bool", "host_ipc": "bool", + "host_dbus": "bool", "privileged": ["NET_ADMIN", "SYS_ADMIN"], "devices": ["/dev/xy"], "logo": "bool", diff --git a/hassio/addons/addon.py b/hassio/addons/addon.py index e24653df9..4dc929b47 100644 --- a/hassio/addons/addon.py +++ b/hassio/addons/addon.py @@ -21,7 +21,8 @@ from ..const import ( STATE_STARTED, STATE_STOPPED, STATE_NONE, ATTR_USER, ATTR_SYSTEM, ATTR_STATE, ATTR_TIMEOUT, ATTR_AUTO_UPDATE, ATTR_NETWORK, ATTR_WEBUI, ATTR_HASSIO_API, ATTR_AUDIO, ATTR_AUDIO_OUTPUT, ATTR_AUDIO_INPUT, - ATTR_GPIO, ATTR_HOMEASSISTANT_API, ATTR_STDIN, ATTR_LEGACY, ATTR_HOST_IPC) + ATTR_GPIO, ATTR_HOMEASSISTANT_API, ATTR_STDIN, ATTR_LEGACY, ATTR_HOST_IPC, + ATTR_HOST_DBUS) from .util import check_installed from ..dock.addon import DockerAddon from ..tools import write_json_file, read_json_file @@ -248,6 +249,11 @@ class Addon(object): """Return True if addon run on host IPC namespace.""" return self._mesh[ATTR_HOST_IPC] + @property + def host_dbus(self): + """Return True if addon run on host DBUS.""" + return self._mesh[ATTR_HOST_DBUS] + @property def devices(self): """Return devices of addon.""" diff --git a/hassio/addons/validate.py b/hassio/addons/validate.py index d24c14535..8efaab9dc 100644 --- a/hassio/addons/validate.py +++ b/hassio/addons/validate.py @@ -16,7 +16,8 @@ from ..const import ( ATTR_LOCATON, ATTR_REPOSITORY, ATTR_TIMEOUT, ATTR_NETWORK, ATTR_UUID, ATTR_AUTO_UPDATE, ATTR_WEBUI, ATTR_AUDIO, ATTR_AUDIO_INPUT, ATTR_HOST_IPC, ATTR_AUDIO_OUTPUT, ATTR_HASSIO_API, ATTR_BUILD_FROM, ATTR_SQUASH, - ATTR_ARGS, ATTR_GPIO, ATTR_HOMEASSISTANT_API, ATTR_STDIN, ATTR_LEGACY) + ATTR_ARGS, ATTR_GPIO, ATTR_HOMEASSISTANT_API, ATTR_STDIN, ATTR_LEGACY, + ATTR_HOST_DBUS) from ..validate import NETWORK_PORT, DOCKER_PORTS, ALSA_CHANNEL _LOGGER = logging.getLogger(__name__) @@ -93,6 +94,7 @@ SCHEMA_ADDON_CONFIG = vol.Schema({ vol.Match(r"^(?:https?|\[PROTO:\w+\]):\/\/\[HOST\]:\[PORT:\d+\].*$"), vol.Optional(ATTR_HOST_NETWORK, default=False): vol.Boolean(), vol.Optional(ATTR_HOST_IPC, default=False): vol.Boolean(), + vol.Optional(ATTR_HOST_DBUS, default=False): vol.Boolean(), vol.Optional(ATTR_DEVICES): [vol.Match(r"^(.*):(.*):([rwm]{1,3})$")], vol.Optional(ATTR_TMPFS): vol.Match(r"^size=(\d)*[kmg](,uid=\d{1,4})?(,rw)?$"), diff --git a/hassio/api/addons.py b/hassio/api/addons.py index 0e9268168..bdb4512ee 100644 --- a/hassio/api/addons.py +++ b/hassio/api/addons.py @@ -14,7 +14,7 @@ from ..const import ( ATTR_INSTALLED, ATTR_LOGO, ATTR_WEBUI, ATTR_DEVICES, ATTR_PRIVILEGED, ATTR_AUDIO, ATTR_AUDIO_INPUT, ATTR_AUDIO_OUTPUT, ATTR_HASSIO_API, ATTR_GPIO, ATTR_HOMEASSISTANT_API, ATTR_STDIN, BOOT_AUTO, BOOT_MANUAL, - ATTR_CHANGELOG, ATTR_HOST_IPC, + ATTR_CHANGELOG, ATTR_HOST_IPC, ATTR_HOST_DBUS, CONTENT_TYPE_PNG, CONTENT_TYPE_BINARY, CONTENT_TYPE_TEXT) from ..validate import DOCKER_PORTS @@ -121,6 +121,7 @@ class APIAddons(object): ATTR_NETWORK: addon.ports, ATTR_HOST_NETWORK: addon.host_network, ATTR_HOST_IPC: addon.host_ipc, + ATTR_HOST_DBUS: addon.host_dbus, ATTR_PRIVILEGED: addon.privileged, ATTR_DEVICES: self._pretty_devices(addon), ATTR_LOGO: addon.with_logo, diff --git a/hassio/const.py b/hassio/const.py index ba9843525..90e3b45c1 100644 --- a/hassio/const.py +++ b/hassio/const.py @@ -103,6 +103,7 @@ ATTR_DEVICES = 'devices' ATTR_ENVIRONMENT = 'environment' ATTR_HOST_NETWORK = 'host_network' ATTR_HOST_IPC = 'host_ipc' +ATTR_HOST_DBUS = 'host_dbus' ATTR_NETWORK = 'network' ATTR_TMPFS = 'tmpfs' ATTR_PRIVILEGED = 'privileged' diff --git a/hassio/dock/addon.py b/hassio/dock/addon.py index 453f11cae..73c943279 100644 --- a/hassio/dock/addon.py +++ b/hassio/dock/addon.py @@ -140,7 +140,7 @@ class DockerAddon(DockerInterface): """Generate volumes for mappings.""" volumes = { str(self.addon.path_extern_data): { - 'bind': '/data', 'mode': 'rw' + 'bind': "/data", 'mode': 'rw' }} addon_mapping = self.addon.map_volumes @@ -149,44 +149,51 @@ class DockerAddon(DockerInterface): if MAP_CONFIG in addon_mapping: volumes.update({ str(self.config.path_extern_config): { - 'bind': '/config', 'mode': addon_mapping[MAP_CONFIG] + 'bind': "/config", 'mode': addon_mapping[MAP_CONFIG] }}) if MAP_SSL in addon_mapping: volumes.update({ str(self.config.path_extern_ssl): { - 'bind': '/ssl', 'mode': addon_mapping[MAP_SSL] + 'bind': "/ssl", 'mode': addon_mapping[MAP_SSL] }}) if MAP_ADDONS in addon_mapping: volumes.update({ str(self.config.path_extern_addons_local): { - 'bind': '/addons', 'mode': addon_mapping[MAP_ADDONS] + 'bind': "/addons", 'mode': addon_mapping[MAP_ADDONS] }}) if MAP_BACKUP in addon_mapping: volumes.update({ str(self.config.path_extern_backup): { - 'bind': '/backup', 'mode': addon_mapping[MAP_BACKUP] + 'bind': "/backup", 'mode': addon_mapping[MAP_BACKUP] }}) if MAP_SHARE in addon_mapping: volumes.update({ str(self.config.path_extern_share): { - 'bind': '/share', 'mode': addon_mapping[MAP_SHARE] + 'bind': "/share", 'mode': addon_mapping[MAP_SHARE] }}) # init other hardware mappings if self.addon.with_gpio: volumes.update({ - '/sys/class/gpio': { - 'bind': '/sys/class/gpio', 'mode': "rw" + "/sys/class/gpio": { + 'bind': "/sys/class/gpio", 'mode': 'rw' }, - '/sys/devices/platform/soc': { - 'bind': '/sys/devices/platform/soc', 'mode': "rw" + "/sys/devices/platform/soc": { + 'bind': "/sys/devices/platform/soc", 'mode': 'rw' }, }) + # host dbus system + if self.addon.host_dbus: + volumes.update({ + "/var/run/dbus": { + 'bind': "/var/run/dbus", 'mode': 'rw' + }}) + return volumes def _run(self): From 110cd32dc301e94697c7aa13fcf864b89f40c3ae Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Tue, 12 Dec 2017 10:41:05 +0100 Subject: [PATCH 14/16] Update hardware.py (#275) --- hassio/hardware.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hassio/hardware.py b/hassio/hardware.py index 09be04acc..ef296dd4e 100644 --- a/hassio/hardware.py +++ b/hassio/hardware.py @@ -20,6 +20,7 @@ PROC_STAT = Path("/proc/stat") RE_BOOT_TIME = re.compile(r"btime (\d+)") GPIO_DEVICES = Path("/sys/class/gpio") +RE_TTY = re.compile(r"tty[A-Z]+") class Hardware(object): @@ -34,7 +35,7 @@ class Hardware(object): """Return all serial and connected devices.""" dev_list = set() for device in self.context.list_devices(subsystem='tty'): - if 'ID_VENDOR' in device: + if 'ID_VENDOR' in device or RE_TTY.match(device.device_node): dev_list.add(device.device_node) return dev_list From c691f2a5594ea62ea745fbeb6a4c5babf6282280 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Tue, 12 Dec 2017 20:01:02 +0100 Subject: [PATCH 15/16] Auto mapping UART devices from host (#276) * Add hardware to docker api * set hardware to docker * add loop to dns * Use loop for dns * Update const.py * Update API.md * Update validate.py * Update addon.py * Update addon.py * fix lint * style * Update hardware.py --- API.md | 1 + hassio/addons/addon.py | 7 ++++++- hassio/addons/validate.py | 3 ++- hassio/const.py | 1 + hassio/core.py | 4 ++-- hassio/dns.py | 4 +++- hassio/dock/__init__.py | 3 ++- hassio/dock/addon.py | 11 +++++++---- hassio/hardware.py | 2 +- 9 files changed, 25 insertions(+), 11 deletions(-) diff --git a/API.md b/API.md index 835138be9..2b5362ad0 100644 --- a/API.md +++ b/API.md @@ -389,6 +389,7 @@ Get all available addons. "host_dbus": "bool", "privileged": ["NET_ADMIN", "SYS_ADMIN"], "devices": ["/dev/xy"], + "auto_uart": "bool", "logo": "bool", "changelog": "bool", "hassio_api": "bool", diff --git a/hassio/addons/addon.py b/hassio/addons/addon.py index 4dc929b47..cb47ce7cc 100644 --- a/hassio/addons/addon.py +++ b/hassio/addons/addon.py @@ -22,7 +22,7 @@ from ..const import ( ATTR_STATE, ATTR_TIMEOUT, ATTR_AUTO_UPDATE, ATTR_NETWORK, ATTR_WEBUI, ATTR_HASSIO_API, ATTR_AUDIO, ATTR_AUDIO_OUTPUT, ATTR_AUDIO_INPUT, ATTR_GPIO, ATTR_HOMEASSISTANT_API, ATTR_STDIN, ATTR_LEGACY, ATTR_HOST_IPC, - ATTR_HOST_DBUS) + ATTR_HOST_DBUS, ATTR_AUTO_UART) from .util import check_installed from ..dock.addon import DockerAddon from ..tools import write_json_file, read_json_file @@ -259,6 +259,11 @@ class Addon(object): """Return devices of addon.""" return self._mesh.get(ATTR_DEVICES) + @property + def auto_uart(self): + """Return True if we should map all uart device.""" + return self._mesh.get(ATTR_AUTO_UART) + @property def tmpfs(self): """Return tmpfs of addon.""" diff --git a/hassio/addons/validate.py b/hassio/addons/validate.py index 8efaab9dc..a0001d289 100644 --- a/hassio/addons/validate.py +++ b/hassio/addons/validate.py @@ -17,7 +17,7 @@ from ..const import ( ATTR_AUTO_UPDATE, ATTR_WEBUI, ATTR_AUDIO, ATTR_AUDIO_INPUT, ATTR_HOST_IPC, ATTR_AUDIO_OUTPUT, ATTR_HASSIO_API, ATTR_BUILD_FROM, ATTR_SQUASH, ATTR_ARGS, ATTR_GPIO, ATTR_HOMEASSISTANT_API, ATTR_STDIN, ATTR_LEGACY, - ATTR_HOST_DBUS) + ATTR_HOST_DBUS, ATTR_AUTO_UART) from ..validate import NETWORK_PORT, DOCKER_PORTS, ALSA_CHANNEL _LOGGER = logging.getLogger(__name__) @@ -96,6 +96,7 @@ SCHEMA_ADDON_CONFIG = vol.Schema({ vol.Optional(ATTR_HOST_IPC, default=False): vol.Boolean(), vol.Optional(ATTR_HOST_DBUS, default=False): vol.Boolean(), vol.Optional(ATTR_DEVICES): [vol.Match(r"^(.*):(.*):([rwm]{1,3})$")], + vol.Optional(ATTR_AUTO_UART, default=False): vol.Boolean(), vol.Optional(ATTR_TMPFS): vol.Match(r"^size=(\d)*[kmg](,uid=\d{1,4})?(,rw)?$"), vol.Optional(ATTR_MAP, default=[]): [vol.Match(RE_VOLUME)], diff --git a/hassio/const.py b/hassio/const.py index 90e3b45c1..1a1bf30b2 100644 --- a/hassio/const.py +++ b/hassio/const.py @@ -66,6 +66,7 @@ ATTR_SOURCE = 'source' ATTR_FEATURES = 'features' ATTR_ADDONS = 'addons' ATTR_VERSION = 'version' +ATTR_AUTO_UART = 'auto_uart' ATTR_LAST_BOOT = 'last_boot' ATTR_LAST_VERSION = 'last_version' ATTR_BETA_CHANNEL = 'beta_channel' diff --git a/hassio/core.py b/hassio/core.py index 6150b0e1b..0043c505b 100644 --- a/hassio/core.py +++ b/hassio/core.py @@ -42,8 +42,8 @@ class HassIO(object): self.scheduler = Scheduler(loop) self.api = RestAPI(config, loop) self.hardware = Hardware() - self.docker = DockerAPI() - self.dns = DNSForward() + self.docker = DockerAPI(self.hardware) + self.dns = DNSForward(loop) # init basic docker container self.supervisor = DockerSupervisor( diff --git a/hassio/dns.py b/hassio/dns.py index e02f0182a..359abadc5 100644 --- a/hassio/dns.py +++ b/hassio/dns.py @@ -11,8 +11,9 @@ COMMAND = "socat UDP-RECVFROM:53,fork UDP-SENDTO:127.0.0.11:53" class DNSForward(object): """Manage DNS forwarding to internal DNS.""" - def __init__(self): + def __init__(self, loop): """Initialize DNS forwarding.""" + self.loop = loop self.proc = None async def start(self): @@ -23,6 +24,7 @@ class DNSForward(object): stdin=asyncio.subprocess.DEVNULL, stdout=asyncio.subprocess.DEVNULL, stderr=asyncio.subprocess.DEVNULL, + loop=self.loop ) except OSError as err: _LOGGER.error("Can't start DNS forwarding -> %s", err) diff --git a/hassio/dock/__init__.py b/hassio/dock/__init__.py index 35d773629..580b51559 100644 --- a/hassio/dock/__init__.py +++ b/hassio/dock/__init__.py @@ -16,11 +16,12 @@ class DockerAPI(object): This class is not AsyncIO safe! """ - def __init__(self): + def __init__(self, hardware): """Initialize docker base wrapper.""" self.docker = docker.DockerClient( base_url="unix:/{}".format(str(SOCKET_DOCKER)), version='auto') self.network = DockerNetwork(self.docker) + self.hardware = hardware @property def images(self): diff --git a/hassio/dock/addon.py b/hassio/dock/addon.py index 73c943279..fa9b075e5 100644 --- a/hassio/dock/addon.py +++ b/hassio/dock/addon.py @@ -80,14 +80,17 @@ class DockerAddon(DockerInterface): """Return needed devices.""" devices = self.addon.devices or [] - # use audio devices + # Use audio devices if self.addon.with_audio and AUDIO_DEVICE not in devices: devices.append(AUDIO_DEVICE) + # Auto mapping UART devices + if self.addon.auto_uart: + for uart_dev in self.docker.hardware.serial_devices: + devices.append("{0}:{0}:rwm".format(uart_dev)) + # Return None if no devices is present - if devices: - return devices - return None + return devices or None @property def ports(self): diff --git a/hassio/hardware.py b/hassio/hardware.py index ef296dd4e..d8ba8eb82 100644 --- a/hassio/hardware.py +++ b/hassio/hardware.py @@ -35,7 +35,7 @@ class Hardware(object): """Return all serial and connected devices.""" dev_list = set() for device in self.context.list_devices(subsystem='tty'): - if 'ID_VENDOR' in device or RE_TTY.match(device.device_node): + if 'ID_VENDOR' in device or RE_TTY.search(device.device_node): dev_list.add(device.device_node) return dev_list From 734923463843e16429f76b777efee566492790d7 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Tue, 12 Dec 2017 23:38:33 +0100 Subject: [PATCH 16/16] Use uvloop & aiohttp C extension (#279) * Update Dockerfile * Update __main__.py * Update Dockerfile * Update Dockerfile * Update Dockerfile * Update Dockerfile * Update Dockerfile * Update Dockerfile * Update Dockerfile * Update Dockerfile * Update Dockerfile --- Dockerfile | 15 ++++++++++++--- hassio/__main__.py | 10 ++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index dd9592d1b..6cf63f798 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,9 +6,18 @@ ENV LANG C.UTF-8 # Setup base RUN apk add --no-cache \ - python3 \ - git \ - socat + python3 \ + git \ + socat \ + libstdc++ \ + && apk add --no-cache --virtual .build-dependencies \ + make \ + python3-dev \ + g++ \ + && pip3 install --no-cache-dir \ + uvloop \ + cchardet \ + && apk del .build-dependencies # Install HassIO COPY . /usr/src/hassio diff --git a/hassio/__main__.py b/hassio/__main__.py index 5ab7639c5..023f28470 100644 --- a/hassio/__main__.py +++ b/hassio/__main__.py @@ -10,9 +10,19 @@ import hassio.core as core _LOGGER = logging.getLogger(__name__) +def attempt_use_uvloop(): + """Attempt to use uvloop.""" + try: + import uvloop + asyncio.set_event_loop_policy(uvloop.EventLoopPolicy()) + except ImportError: + pass + + # pylint: disable=invalid-name if __name__ == "__main__": bootstrap.initialize_logging() + attempt_use_uvloop() loop = asyncio.get_event_loop() if not bootstrap.check_environment():