Merge pull request #796 from home-assistant/dev

Release 139
This commit is contained in:
Pascal Vizeli 2018-11-05 16:19:17 +01:00 committed by GitHub
commit 6e7cf5e4c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 44 additions and 25 deletions

2
API.md
View File

@ -415,7 +415,7 @@ Proxy to real websocket instance.
### RESTful for API addons ### RESTful for API addons
If a add-on will call itself, you can use `/addons/self/...`. If an add-on will call itself, you can use `/addons/self/...`.
- GET `/addons` - GET `/addons`

View File

@ -674,7 +674,8 @@ class Addon(CoreSysAttributes):
"""Install an add-on.""" """Install an add-on."""
if not self.available: if not self.available:
_LOGGER.error( _LOGGER.error(
"Add-on %s not supported on %s", self._id, self.sys_arch) "Add-on %s not supported on %s with %s architecture",
self._id, self.sys_machine, self.sys_arch)
return False return False
if self.is_installed: if self.is_installed:

View File

@ -2,12 +2,13 @@
import logging import logging
from aiohttp import BasicAuth from aiohttp import BasicAuth
from aiohttp.hdrs import CONTENT_TYPE, AUTHORIZATION from aiohttp.web_exceptions import HTTPUnauthorized
from aiohttp.hdrs import CONTENT_TYPE, AUTHORIZATION, WWW_AUTHENTICATE
from .utils import api_process from .utils import api_process
from ..const import REQUEST_FROM, CONTENT_TYPE_JSON, CONTENT_TYPE_URL from ..const import REQUEST_FROM, CONTENT_TYPE_JSON, CONTENT_TYPE_URL
from ..coresys import CoreSysAttributes from ..coresys import CoreSysAttributes
from ..exceptions import APIError, APIForbidden from ..exceptions import APIForbidden
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -55,4 +56,6 @@ class APIAuth(CoreSysAttributes):
data = await request.post() data = await request.post()
return await self._process_dict(request, addon, data) return await self._process_dict(request, addon, data)
raise APIError("Auth method not detected!") raise HTTPUnauthorized(headers={
WWW_AUTHENTICATE: "Basic realm=\"Hass.io Authentication\""
})

View File

@ -153,7 +153,7 @@ class APIProxy(CoreSysAttributes):
except (RuntimeError, ValueError, ClientConnectorError) as err: except (RuntimeError, ValueError, ClientConnectorError) as err:
_LOGGER.error("Client error on WebSocket API %s.", err) _LOGGER.error("Client error on WebSocket API %s.", err)
except HomeAssistantAuthError as err: except HomeAssistantAuthError:
_LOGGER.error("Failed authentication to Home Assistant WebSocket") _LOGGER.error("Failed authentication to Home Assistant WebSocket")
raise APIError() raise APIError()

View File

@ -2,7 +2,7 @@
from pathlib import Path from pathlib import Path
from ipaddress import ip_network from ipaddress import ip_network
HASSIO_VERSION = '138' HASSIO_VERSION = '139'
URL_HASSIO_ADDONS = "https://github.com/home-assistant/hassio-addons" URL_HASSIO_ADDONS = "https://github.com/home-assistant/hassio-addons"
URL_HASSIO_VERSION = \ URL_HASSIO_VERSION = \
@ -259,3 +259,6 @@ ROLE_HOMEASSISTANT = 'homeassistant'
ROLE_BACKUP = 'backup' ROLE_BACKUP = 'backup'
ROLE_MANAGER = 'manager' ROLE_MANAGER = 'manager'
ROLE_ADMIN = 'admin' ROLE_ADMIN = 'admin'
CHAN_ID = 'chan_id'
CHAN_TYPE = 'chan_type'

View File

@ -36,6 +36,7 @@ class Discovery(CoreSysAttributes, JsonConfig):
discovery = Message(**message) discovery = Message(**message)
messages[discovery.uuid] = discovery messages[discovery.uuid] = discovery
_LOGGER.info("Load %d messages", len(messages))
self.message_obj = messages self.message_obj = messages
def save(self): def save(self):
@ -60,7 +61,7 @@ class Discovery(CoreSysAttributes, JsonConfig):
def send(self, addon, service, config): def send(self, addon, service, config):
"""Send a discovery message to Home Assistant.""" """Send a discovery message to Home Assistant."""
try: try:
DISCOVERY_SERVICES[service](config) config = DISCOVERY_SERVICES[service](config)
except vol.Invalid as err: except vol.Invalid as err:
_LOGGER.error( _LOGGER.error(
"Invalid discovery %s config", humanize_error(config, err)) "Invalid discovery %s config", humanize_error(config, err))
@ -115,7 +116,7 @@ class Discovery(CoreSysAttributes, JsonConfig):
@attr.s @attr.s
class Message: class Message:
"""Represent a single Discovery message.""" """Represent a single Discovery message."""
uuid = attr.ib(factory=lambda: uuid4().hex, cmp=False, init=False)
addon = attr.ib() addon = attr.ib()
service = attr.ib() service = attr.ib()
config = attr.ib(cmp=False) config = attr.ib(cmp=False)
uuid = attr.ib(factory=lambda: uuid4().hex, cmp=False)

View File

@ -66,7 +66,7 @@ class HassOS(CoreSysAttributes):
return self._board return self._board
def _check_host(self): def _check_host(self):
"""Check if HassOS is availabe.""" """Check if HassOS is available."""
if not self.available: if not self.available:
_LOGGER.error("No HassOS available") _LOGGER.error("No HassOS available")
raise HassOSNotSupportedError() raise HassOSNotSupportedError()

View File

@ -191,7 +191,7 @@ class HomeAssistant(JsonConfig, CoreSysAttributes):
@property @property
def hassio_token(self): def hassio_token(self):
"""Return a access token for the Hass.io API.""" """Return an access token for the Hass.io API."""
return self._data.get(ATTR_ACCESS_TOKEN) return self._data.get(ATTR_ACCESS_TOKEN)
@property @property
@ -260,7 +260,7 @@ class HomeAssistant(JsonConfig, CoreSysAttributes):
_LOGGER.warning("Version %s is already installed", version) _LOGGER.warning("Version %s is already installed", version)
return HomeAssistantUpdateError() return HomeAssistantUpdateError()
# process a update # process an update
async def _update(to_version): async def _update(to_version):
"""Run Home Assistant update.""" """Run Home Assistant update."""
try: try:

View File

@ -6,7 +6,8 @@ from string import Template
import attr import attr
from ..const import ATTR_INPUT, ATTR_OUTPUT, ATTR_DEVICES, ATTR_NAME from ..const import (
ATTR_INPUT, ATTR_OUTPUT, ATTR_DEVICES, ATTR_NAME, CHAN_ID, CHAN_TYPE)
from ..coresys import CoreSysAttributes from ..coresys import CoreSysAttributes
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -58,7 +59,9 @@ class AlsaAudio(CoreSysAttributes):
# Process devices # Process devices
for dev_id, dev_data in self.sys_hardware.audio_devices.items(): for dev_id, dev_data in self.sys_hardware.audio_devices.items():
for chan_id, chan_type in dev_data[ATTR_DEVICES].items(): for chan_info in dev_data[ATTR_DEVICES]:
chan_id = chan_info[CHAN_ID]
chan_type = chan_info[CHAN_TYPE]
alsa_id = f"{dev_id},{chan_id}" alsa_id = f"{dev_id},{chan_id}"
dev_name = dev_data[ATTR_NAME] dev_name = dev_data[ATTR_NAME]

View File

@ -6,7 +6,7 @@ import re
import pyudev import pyudev
from ..const import ATTR_NAME, ATTR_TYPE, ATTR_DEVICES from ..const import ATTR_NAME, ATTR_TYPE, ATTR_DEVICES, CHAN_ID, CHAN_TYPE
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -87,14 +87,16 @@ class Hardware:
audio_list[match.group(1)] = { audio_list[match.group(1)] = {
ATTR_NAME: match.group(3), ATTR_NAME: match.group(3),
ATTR_TYPE: match.group(2), ATTR_TYPE: match.group(2),
ATTR_DEVICES: {}, ATTR_DEVICES: [],
} }
# parse devices # parse devices
for match in RE_DEVICES.finditer(devices): for match in RE_DEVICES.finditer(devices):
try: try:
audio_list[match.group(1)][ATTR_DEVICES][match.group(2)] = \ audio_list[match.group(1)][ATTR_DEVICES].append({
match.group(3) CHAN_ID: match.group(2),
CHAN_TYPE: match.group(3)
})
except KeyError: except KeyError:
_LOGGER.warning("Wrong audio device found %s", match.group(0)) _LOGGER.warning("Wrong audio device found %s", match.group(0))
continue continue

View File

@ -118,7 +118,7 @@ class SnapshotManager(CoreSysAttributes):
async def do_snapshot_full(self, name="", password=None): async def do_snapshot_full(self, name="", password=None):
"""Create a full snapshot.""" """Create a full snapshot."""
if self.lock.locked(): if self.lock.locked():
_LOGGER.error("It is already a snapshot/restore process running") _LOGGER.error("A snapshot/restore process is already running")
return None return None
snapshot = self._create_snapshot(name, SNAPSHOT_FULL, password) snapshot = self._create_snapshot(name, SNAPSHOT_FULL, password)
@ -153,7 +153,7 @@ class SnapshotManager(CoreSysAttributes):
password=None): password=None):
"""Create a partial snapshot.""" """Create a partial snapshot."""
if self.lock.locked(): if self.lock.locked():
_LOGGER.error("It is already a snapshot/restore process running") _LOGGER.error("A snapshot/restore process is already running")
return None return None
addons = addons or [] addons = addons or []
@ -201,7 +201,7 @@ class SnapshotManager(CoreSysAttributes):
async def do_restore_full(self, snapshot, password=None): async def do_restore_full(self, snapshot, password=None):
"""Restore a snapshot.""" """Restore a snapshot."""
if self.lock.locked(): if self.lock.locked():
_LOGGER.error("It is already a snapshot/restore process running") _LOGGER.error("A snapshot/restore process is already running")
return False return False
if snapshot.sys_type != SNAPSHOT_FULL: if snapshot.sys_type != SNAPSHOT_FULL:
@ -274,7 +274,7 @@ class SnapshotManager(CoreSysAttributes):
addons=None, folders=None, password=None): addons=None, folders=None, password=None):
"""Restore a snapshot.""" """Restore a snapshot."""
if self.lock.locked(): if self.lock.locked():
_LOGGER.error("It is already a snapshot/restore process running") _LOGGER.error("A snapshot/restore process is already running")
return False return False
if snapshot.protected and not snapshot.set_password(password): if snapshot.protected and not snapshot.set_password(password):

View File

@ -3,6 +3,7 @@ import asyncio
import logging import logging
from .coresys import CoreSysAttributes from .coresys import CoreSysAttributes
from .exceptions import HomeAssistantError
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -104,7 +105,10 @@ class Tasks(CoreSysAttributes):
return return
_LOGGER.warning("Watchdog found a problem with Home Assistant Docker!") _LOGGER.warning("Watchdog found a problem with Home Assistant Docker!")
await self.sys_homeassistant.start() try:
await self.sys_homeassistant.start()
except HomeAssistantError:
_LOGGER.error("Watchdog Home Assistant reanimation fails!")
async def _watchdog_homeassistant_api(self): async def _watchdog_homeassistant_api(self):
"""Create scheduler task for monitoring running state of API. """Create scheduler task for monitoring running state of API.
@ -136,6 +140,8 @@ class Tasks(CoreSysAttributes):
_LOGGER.error("Watchdog found a problem with Home Assistant API!") _LOGGER.error("Watchdog found a problem with Home Assistant API!")
try: try:
await self.sys_homeassistant.restart() await self.sys_homeassistant.restart()
except HomeAssistantError:
_LOGGER.error("Watchdog Home Assistant reanimation fails!")
finally: finally:
self._cache[HASS_WATCHDOG_API] = 0 self._cache[HASS_WATCHDOG_API] = 0

View File

@ -1,4 +1,4 @@
attr==0.3.1 attrs==18.2.0
async_timeout==3.0.1 async_timeout==3.0.1
aiohttp==3.4.4 aiohttp==3.4.4
docker==3.5.0 docker==3.5.0

View File

@ -3,7 +3,7 @@ envlist = lint
[testenv] [testenv]
deps = deps =
flake8==3.5.0 flake8==3.6.0
pylint==2.1.1 pylint==2.1.1
-r{toxinidir}/requirements.txt -r{toxinidir}/requirements.txt