mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-18 22:56:31 +00:00
commit
6e7cf5e4c9
2
API.md
2
API.md
@ -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`
|
||||||
|
|
||||||
|
@ -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:
|
||||||
|
@ -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\""
|
||||||
|
})
|
||||||
|
@ -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()
|
||||||
|
@ -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'
|
||||||
|
@ -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)
|
||||||
|
@ -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()
|
||||||
|
@ -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:
|
||||||
|
@ -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]
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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):
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user