Update docstrings, comments and log messages (#707)
This commit is contained in:
parent
67dcf1563b
commit
267791833e
|
@ -1,4 +1,4 @@
|
|||
"""Init file for HassIO addons."""
|
||||
"""Init file for Hass.io add-ons."""
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
|
@ -14,10 +14,10 @@ BUILTIN_REPOSITORIES = set((REPOSITORY_CORE, REPOSITORY_LOCAL))
|
|||
|
||||
|
||||
class AddonManager(CoreSysAttributes):
|
||||
"""Manage addons inside HassIO."""
|
||||
"""Manage add-ons inside Hass.io."""
|
||||
|
||||
def __init__(self, coresys):
|
||||
"""Initialize docker base wrapper."""
|
||||
"""Initialize Docker base wrapper."""
|
||||
self.coresys = coresys
|
||||
self.data = AddonsData(coresys)
|
||||
self.addons_obj = {}
|
||||
|
@ -25,18 +25,18 @@ class AddonManager(CoreSysAttributes):
|
|||
|
||||
@property
|
||||
def list_addons(self):
|
||||
"""Return a list of all addons."""
|
||||
"""Return a list of all add-ons."""
|
||||
return list(self.addons_obj.values())
|
||||
|
||||
@property
|
||||
def list_installed(self):
|
||||
"""Return a list of installed addons."""
|
||||
"""Return a list of installed add-ons."""
|
||||
return [addon for addon in self.addons_obj.values()
|
||||
if addon.is_installed]
|
||||
|
||||
@property
|
||||
def list_repositories(self):
|
||||
"""Return list of addon repositories."""
|
||||
"""Return list of add-on repositories."""
|
||||
return list(self.repositories_obj.values())
|
||||
|
||||
def get(self, addon_slug):
|
||||
|
@ -44,32 +44,32 @@ class AddonManager(CoreSysAttributes):
|
|||
return self.addons_obj.get(addon_slug)
|
||||
|
||||
def from_uuid(self, uuid):
|
||||
"""Return an add-on from uuid."""
|
||||
"""Return an add-on from UUID."""
|
||||
for addon in self.list_addons:
|
||||
if addon.is_installed and uuid == addon.uuid:
|
||||
return addon
|
||||
return None
|
||||
|
||||
def from_token(self, token):
|
||||
"""Return an add-on from hassio token."""
|
||||
"""Return an add-on from Hass.io token."""
|
||||
for addon in self.list_addons:
|
||||
if addon.is_installed and token == addon.hassio_token:
|
||||
return addon
|
||||
return None
|
||||
|
||||
async def load(self):
|
||||
"""Startup addon management."""
|
||||
"""Start up add-on management."""
|
||||
self.data.reload()
|
||||
|
||||
# init hassio built-in repositories
|
||||
# Init Hass.io built-in repositories
|
||||
repositories = \
|
||||
set(self.sys_config.addons_repositories) | BUILTIN_REPOSITORIES
|
||||
|
||||
# init custom repositories & load addons
|
||||
# Init custom repositories and load add-ons
|
||||
await self.load_repositories(repositories)
|
||||
|
||||
async def reload(self):
|
||||
"""Update addons from repo and reload list."""
|
||||
"""Update add-ons from repository and reload list."""
|
||||
tasks = [repository.update() for repository in
|
||||
self.repositories_obj.values()]
|
||||
if tasks:
|
||||
|
@ -113,14 +113,14 @@ class AddonManager(CoreSysAttributes):
|
|||
await self.load_addons()
|
||||
|
||||
async def load_addons(self):
|
||||
"""Update/add internal addon store."""
|
||||
"""Update/add internal add-on store."""
|
||||
all_addons = set(self.data.system) | set(self.data.cache)
|
||||
|
||||
# calc diff
|
||||
add_addons = all_addons - set(self.addons_obj)
|
||||
del_addons = set(self.addons_obj) - all_addons
|
||||
|
||||
_LOGGER.info("Load addons: %d all - %d new - %d remove",
|
||||
_LOGGER.info("Load add-ons: %d all - %d new - %d remove",
|
||||
len(all_addons), len(add_addons), len(del_addons))
|
||||
|
||||
# new addons
|
||||
|
@ -139,14 +139,14 @@ class AddonManager(CoreSysAttributes):
|
|||
self.addons_obj.pop(addon_slug)
|
||||
|
||||
async def boot(self, stage):
|
||||
"""Boot addons with mode auto."""
|
||||
"""Boot add-ons with mode auto."""
|
||||
tasks = []
|
||||
for addon in self.addons_obj.values():
|
||||
if addon.is_installed and addon.boot == BOOT_AUTO and \
|
||||
addon.startup == stage:
|
||||
tasks.append(addon.start())
|
||||
|
||||
_LOGGER.info("Startup %s run %d addons", stage, len(tasks))
|
||||
_LOGGER.info("Startup %s run %d add-ons", stage, len(tasks))
|
||||
if tasks:
|
||||
await asyncio.wait(tasks)
|
||||
await asyncio.sleep(self.sys_config.wait_boot)
|
||||
|
@ -160,6 +160,6 @@ class AddonManager(CoreSysAttributes):
|
|||
addon.startup == stage:
|
||||
tasks.append(addon.stop())
|
||||
|
||||
_LOGGER.info("Shutdown %s stop %d addons", stage, len(tasks))
|
||||
_LOGGER.info("Shutdown %s stop %d add-ons", stage, len(tasks))
|
||||
if tasks:
|
||||
await asyncio.wait(tasks)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""Init file for HassIO addons."""
|
||||
"""Init file for Hass.io add-ons."""
|
||||
from contextlib import suppress
|
||||
from copy import deepcopy
|
||||
import logging
|
||||
|
@ -43,7 +43,7 @@ RE_WEBUI = re.compile(
|
|||
|
||||
|
||||
class Addon(CoreSysAttributes):
|
||||
"""Hold data for addon inside HassIO."""
|
||||
"""Hold data for add-on inside Hass.io."""
|
||||
|
||||
def __init__(self, coresys, slug):
|
||||
"""Initialize data holder."""
|
||||
|
@ -59,27 +59,27 @@ class Addon(CoreSysAttributes):
|
|||
|
||||
@property
|
||||
def slug(self):
|
||||
"""Return slug/id of addon."""
|
||||
"""Return slug/id of add-on."""
|
||||
return self._id
|
||||
|
||||
@property
|
||||
def _mesh(self):
|
||||
"""Return addon data from system or cache."""
|
||||
"""Return add-on data from system or cache."""
|
||||
return self._data.system.get(self._id, self._data.cache.get(self._id))
|
||||
|
||||
@property
|
||||
def _data(self):
|
||||
"""Return addons data storage."""
|
||||
"""Return add-ons data storage."""
|
||||
return self.sys_addons.data
|
||||
|
||||
@property
|
||||
def is_installed(self):
|
||||
"""Return True if an addon is installed."""
|
||||
"""Return True if an add-on is installed."""
|
||||
return self._id in self._data.system
|
||||
|
||||
@property
|
||||
def is_detached(self):
|
||||
"""Return True if addon is detached."""
|
||||
"""Return True if add-on is detached."""
|
||||
return self._id not in self._data.cache
|
||||
|
||||
@property
|
||||
|
@ -97,19 +97,19 @@ class Addon(CoreSysAttributes):
|
|||
self._data.save_data()
|
||||
|
||||
def _set_uninstall(self):
|
||||
"""Set addon as uninstalled."""
|
||||
"""Set add-on as uninstalled."""
|
||||
self._data.system.pop(self._id, None)
|
||||
self._data.user.pop(self._id, None)
|
||||
self._data.save_data()
|
||||
|
||||
def _set_update(self, version):
|
||||
"""Update version of addon."""
|
||||
"""Update version of add-on."""
|
||||
self._data.system[self._id] = deepcopy(self._data.cache[self._id])
|
||||
self._data.user[self._id][ATTR_VERSION] = version
|
||||
self._data.save_data()
|
||||
|
||||
def _restore_data(self, user, system):
|
||||
"""Restore data to addon."""
|
||||
"""Restore data to add-on."""
|
||||
self._data.user[self._id] = deepcopy(user)
|
||||
self._data.system[self._id] = deepcopy(system)
|
||||
self._data.save_data()
|
||||
|
@ -126,7 +126,7 @@ class Addon(CoreSysAttributes):
|
|||
|
||||
@options.setter
|
||||
def options(self, value):
|
||||
"""Store user addon options."""
|
||||
"""Store user add-on options."""
|
||||
if value is None:
|
||||
self._data.user[self._id][ATTR_OPTIONS] = {}
|
||||
else:
|
||||
|
@ -158,7 +158,7 @@ class Addon(CoreSysAttributes):
|
|||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return name of addon."""
|
||||
"""Return name of add-on."""
|
||||
return self._mesh[ATTR_NAME]
|
||||
|
||||
@property
|
||||
|
@ -175,14 +175,14 @@ class Addon(CoreSysAttributes):
|
|||
|
||||
@property
|
||||
def hassio_token(self):
|
||||
"""Return access token for hass.io API."""
|
||||
"""Return access token for Hass.io API."""
|
||||
if self.is_installed:
|
||||
return self._data.user[self._id].get(ATTR_ACCESS_TOKEN)
|
||||
return None
|
||||
|
||||
@property
|
||||
def description(self):
|
||||
"""Return description of addon."""
|
||||
"""Return description of add-on."""
|
||||
return self._mesh[ATTR_DESCRIPTON]
|
||||
|
||||
@property
|
||||
|
@ -200,31 +200,31 @@ class Addon(CoreSysAttributes):
|
|||
|
||||
@property
|
||||
def repository(self):
|
||||
"""Return repository of addon."""
|
||||
"""Return repository of add-on."""
|
||||
return self._mesh[ATTR_REPOSITORY]
|
||||
|
||||
@property
|
||||
def last_version(self):
|
||||
"""Return version of addon."""
|
||||
"""Return version of add-on."""
|
||||
if self._id in self._data.cache:
|
||||
return self._data.cache[self._id][ATTR_VERSION]
|
||||
return self.version_installed
|
||||
|
||||
@property
|
||||
def protected(self):
|
||||
"""Return if addon is in protected mode."""
|
||||
"""Return if add-on is in protected mode."""
|
||||
if self.is_installed:
|
||||
return self._data.user[self._id][ATTR_PROTECTED]
|
||||
return True
|
||||
|
||||
@protected.setter
|
||||
def protected(self, value):
|
||||
"""Set addon in protected mode."""
|
||||
"""Set add-on in protected mode."""
|
||||
self._data.user[self._id][ATTR_PROTECTED] = value
|
||||
|
||||
@property
|
||||
def startup(self):
|
||||
"""Return startup type of addon."""
|
||||
"""Return startup type of add-on."""
|
||||
return self._mesh.get(ATTR_STARTUP)
|
||||
|
||||
@property
|
||||
|
@ -249,7 +249,7 @@ class Addon(CoreSysAttributes):
|
|||
|
||||
@property
|
||||
def ports(self):
|
||||
"""Return ports of addon."""
|
||||
"""Return ports of add-on."""
|
||||
if self.host_network or ATTR_PORTS not in self._mesh:
|
||||
return None
|
||||
|
||||
|
@ -260,7 +260,7 @@ class Addon(CoreSysAttributes):
|
|||
|
||||
@ports.setter
|
||||
def ports(self, value):
|
||||
"""Set custom ports of addon."""
|
||||
"""Set custom ports of add-on."""
|
||||
if value is None:
|
||||
self._data.user[self._id].pop(ATTR_NETWORK, None)
|
||||
else:
|
||||
|
@ -304,42 +304,42 @@ class Addon(CoreSysAttributes):
|
|||
|
||||
@property
|
||||
def host_network(self):
|
||||
"""Return True if addon run on host network."""
|
||||
"""Return True if add-on run on host network."""
|
||||
return self._mesh[ATTR_HOST_NETWORK]
|
||||
|
||||
@property
|
||||
def host_pid(self):
|
||||
"""Return True if addon run on host PID namespace."""
|
||||
"""Return True if add-on run on host PID namespace."""
|
||||
return self._mesh[ATTR_HOST_PID]
|
||||
|
||||
@property
|
||||
def host_ipc(self):
|
||||
"""Return True if addon run on host IPC namespace."""
|
||||
"""Return True if add-on 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 True if add-on run on host D-BUS."""
|
||||
return self._mesh[ATTR_HOST_DBUS]
|
||||
|
||||
@property
|
||||
def devices(self):
|
||||
"""Return devices of addon."""
|
||||
"""Return devices of add-on."""
|
||||
return self._mesh.get(ATTR_DEVICES)
|
||||
|
||||
@property
|
||||
def auto_uart(self):
|
||||
"""Return True if we should map all uart device."""
|
||||
"""Return True if we should map all UART device."""
|
||||
return self._mesh.get(ATTR_AUTO_UART)
|
||||
|
||||
@property
|
||||
def tmpfs(self):
|
||||
"""Return tmpfs of addon."""
|
||||
"""Return tmpfs of add-on."""
|
||||
return self._mesh.get(ATTR_TMPFS)
|
||||
|
||||
@property
|
||||
def environment(self):
|
||||
"""Return environment of addon."""
|
||||
"""Return environment of add-on."""
|
||||
return self._mesh.get(ATTR_ENVIRONMENT)
|
||||
|
||||
@property
|
||||
|
@ -349,7 +349,7 @@ class Addon(CoreSysAttributes):
|
|||
|
||||
@property
|
||||
def apparmor(self):
|
||||
"""Return True if apparmor is enabled."""
|
||||
"""Return True if AppArmor is enabled."""
|
||||
if not self._mesh.get(ATTR_APPARMOR):
|
||||
return SECURITY_DISABLE
|
||||
elif self.sys_host.apparmor.exists(self.slug):
|
||||
|
@ -358,22 +358,22 @@ class Addon(CoreSysAttributes):
|
|||
|
||||
@property
|
||||
def legacy(self):
|
||||
"""Return if the add-on don't support hass labels."""
|
||||
"""Return if the add-on don't support Home Assistant labels."""
|
||||
return self._mesh.get(ATTR_LEGACY)
|
||||
|
||||
@property
|
||||
def access_docker_api(self):
|
||||
"""Return if the add-on need read-only docker API access."""
|
||||
"""Return if the add-on need read-only Docker API access."""
|
||||
return self._mesh.get(ATTR_DOCKER_API)
|
||||
|
||||
@property
|
||||
def access_hassio_api(self):
|
||||
"""Return True if the add-on access to hassio api."""
|
||||
"""Return True if the add-on access to Hass.io REASTful API."""
|
||||
return self._mesh[ATTR_HASSIO_API]
|
||||
|
||||
@property
|
||||
def access_homeassistant_api(self):
|
||||
"""Return True if the add-on access to Home-Assistant api proxy."""
|
||||
"""Return True if the add-on access to Home Assistant API proxy."""
|
||||
return self._mesh[ATTR_HOMEASSISTANT_API]
|
||||
|
||||
@property
|
||||
|
@ -388,7 +388,7 @@ class Addon(CoreSysAttributes):
|
|||
|
||||
@property
|
||||
def with_gpio(self):
|
||||
"""Return True if the add-on access to gpio interface."""
|
||||
"""Return True if the add-on access to GPIO interface."""
|
||||
return self._mesh[ATTR_GPIO]
|
||||
|
||||
@property
|
||||
|
@ -445,7 +445,7 @@ class Addon(CoreSysAttributes):
|
|||
|
||||
@property
|
||||
def url(self):
|
||||
"""Return url of addon."""
|
||||
"""Return URL of add-on."""
|
||||
return self._mesh.get(ATTR_URL)
|
||||
|
||||
@property
|
||||
|
@ -470,10 +470,10 @@ class Addon(CoreSysAttributes):
|
|||
|
||||
@property
|
||||
def image(self):
|
||||
"""Return image name of addon."""
|
||||
"""Return image name of add-on."""
|
||||
addon_data = self._mesh
|
||||
|
||||
# Repository with dockerhub images
|
||||
# Repository with Dockerhub images
|
||||
if ATTR_IMAGE in addon_data:
|
||||
return addon_data[ATTR_IMAGE].format(arch=self.sys_arch)
|
||||
|
||||
|
@ -484,12 +484,12 @@ class Addon(CoreSysAttributes):
|
|||
|
||||
@property
|
||||
def need_build(self):
|
||||
"""Return True if this addon need a local build."""
|
||||
"""Return True if this add-on need a local build."""
|
||||
return ATTR_IMAGE not in self._mesh
|
||||
|
||||
@property
|
||||
def map_volumes(self):
|
||||
"""Return a dict of {volume: policy} from addon."""
|
||||
"""Return a dict of {volume: policy} from add-on."""
|
||||
volumes = {}
|
||||
for volume in self._mesh[ATTR_MAP]:
|
||||
result = RE_VOLUME.match(volume)
|
||||
|
@ -499,37 +499,37 @@ class Addon(CoreSysAttributes):
|
|||
|
||||
@property
|
||||
def path_data(self):
|
||||
"""Return addon data path inside supervisor."""
|
||||
"""Return add-on data path inside Supervisor."""
|
||||
return Path(self.sys_config.path_addons_data, self._id)
|
||||
|
||||
@property
|
||||
def path_extern_data(self):
|
||||
"""Return addon data path external for docker."""
|
||||
"""Return add-on data path external for Docker."""
|
||||
return PurePath(self.sys_config.path_extern_addons_data, self._id)
|
||||
|
||||
@property
|
||||
def path_options(self):
|
||||
"""Return path to addons options."""
|
||||
"""Return path to add-on options."""
|
||||
return Path(self.path_data, "options.json")
|
||||
|
||||
@property
|
||||
def path_location(self):
|
||||
"""Return path to this addon."""
|
||||
"""Return path to this add-on."""
|
||||
return Path(self._mesh[ATTR_LOCATON])
|
||||
|
||||
@property
|
||||
def path_icon(self):
|
||||
"""Return path to addon icon."""
|
||||
"""Return path to add-on icon."""
|
||||
return Path(self.path_location, 'icon.png')
|
||||
|
||||
@property
|
||||
def path_logo(self):
|
||||
"""Return path to addon logo."""
|
||||
"""Return path to add-on logo."""
|
||||
return Path(self.path_location, 'logo.png')
|
||||
|
||||
@property
|
||||
def path_changelog(self):
|
||||
"""Return path to addon changelog."""
|
||||
"""Return path to add-on changelog."""
|
||||
return Path(self.path_location, 'CHANGELOG.md')
|
||||
|
||||
@property
|
||||
|
@ -544,15 +544,15 @@ class Addon(CoreSysAttributes):
|
|||
|
||||
@property
|
||||
def path_extern_asound(self):
|
||||
"""Return path to asound config for docker."""
|
||||
"""Return path to asound config for Docker."""
|
||||
return Path(self.sys_config.path_extern_tmp, f"{self.slug}_asound")
|
||||
|
||||
def save_data(self):
|
||||
"""Save data of addon."""
|
||||
"""Save data of add-on."""
|
||||
self.sys_addons.data.save_data()
|
||||
|
||||
def write_options(self):
|
||||
"""Return True if addon options is written to data."""
|
||||
"""Return True if add-on options is written to data."""
|
||||
schema = self.schema
|
||||
options = self.options
|
||||
|
||||
|
@ -560,10 +560,10 @@ class Addon(CoreSysAttributes):
|
|||
schema(options)
|
||||
write_json_file(self.path_options, options)
|
||||
except vol.Invalid as ex:
|
||||
_LOGGER.error("Addon %s have wrong options: %s", self._id,
|
||||
_LOGGER.error("Add-on %s have wrong options: %s", self._id,
|
||||
humanize_error(options, ex))
|
||||
except (OSError, json.JSONDecodeError) as err:
|
||||
_LOGGER.error("Addon %s can't write options: %s", self._id, err)
|
||||
_LOGGER.error("Add-on %s can't write options: %s", self._id, err)
|
||||
else:
|
||||
return True
|
||||
|
||||
|
@ -578,7 +578,7 @@ class Addon(CoreSysAttributes):
|
|||
with self.path_asound.open('w') as config_file:
|
||||
config_file.write(asound_config)
|
||||
except OSError as err:
|
||||
_LOGGER.error("Addon %s can't write asound: %s", self._id, err)
|
||||
_LOGGER.error("Add-on %s can't write asound: %s", self._id, err)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
@ -606,7 +606,7 @@ class Addon(CoreSysAttributes):
|
|||
|
||||
@property
|
||||
def schema(self):
|
||||
"""Create a schema for addon options."""
|
||||
"""Create a schema for add-on options."""
|
||||
raw_schema = self._mesh[ATTR_SCHEMA]
|
||||
|
||||
if isinstance(raw_schema, bool):
|
||||
|
@ -614,7 +614,7 @@ class Addon(CoreSysAttributes):
|
|||
return vol.Schema(vol.All(dict, validate_options(raw_schema)))
|
||||
|
||||
def test_update_schema(self):
|
||||
"""Check if the exists config valid after update."""
|
||||
"""Check if the existing configuration is valid after update."""
|
||||
if not self.is_installed or self.is_detached:
|
||||
return True
|
||||
|
||||
|
@ -644,19 +644,19 @@ class Addon(CoreSysAttributes):
|
|||
return True
|
||||
|
||||
async def install(self):
|
||||
"""Install an addon."""
|
||||
"""Install an add-on."""
|
||||
if self.sys_arch not in self.supported_arch:
|
||||
_LOGGER.error(
|
||||
"Addon %s not supported on %s", self._id, self.sys_arch)
|
||||
"Add-on %s not supported on %s", self._id, self.sys_arch)
|
||||
return False
|
||||
|
||||
if self.is_installed:
|
||||
_LOGGER.error("Addon %s is already installed", self._id)
|
||||
_LOGGER.error("Add-on %s is already installed", self._id)
|
||||
return False
|
||||
|
||||
if not self.path_data.is_dir():
|
||||
_LOGGER.info(
|
||||
"Create Home-Assistant addon data folder %s", self.path_data)
|
||||
"Create Home Assistant add-on data folder %s", self.path_data)
|
||||
self.path_data.mkdir()
|
||||
|
||||
# Setup/Fix AppArmor profile
|
||||
|
@ -670,13 +670,13 @@ class Addon(CoreSysAttributes):
|
|||
|
||||
@check_installed
|
||||
async def uninstall(self):
|
||||
"""Remove an addon."""
|
||||
"""Remove an add-on."""
|
||||
if not await self.instance.remove():
|
||||
return False
|
||||
|
||||
if self.path_data.is_dir():
|
||||
_LOGGER.info(
|
||||
"Remove Home-Assistant addon data folder %s", self.path_data)
|
||||
"Remove Home Assistant add-on data folder %s", self.path_data)
|
||||
await remove_data(self.path_data)
|
||||
|
||||
# Cleanup audio settings
|
||||
|
@ -684,7 +684,7 @@ class Addon(CoreSysAttributes):
|
|||
with suppress(OSError):
|
||||
self.path_asound.unlink()
|
||||
|
||||
# Cleanup apparmor profile
|
||||
# Cleanup AppArmor profile
|
||||
if self.sys_host.apparmor.exists(self.slug):
|
||||
with suppress(HostAppArmorError):
|
||||
await self.sys_host.apparmor.remove_profile(self.slug)
|
||||
|
@ -693,7 +693,7 @@ class Addon(CoreSysAttributes):
|
|||
return True
|
||||
|
||||
async def state(self):
|
||||
"""Return running state of addon."""
|
||||
"""Return running state of add-on."""
|
||||
if not self.is_installed:
|
||||
return STATE_NONE
|
||||
|
||||
|
@ -703,9 +703,9 @@ class Addon(CoreSysAttributes):
|
|||
|
||||
@check_installed
|
||||
async def start(self):
|
||||
"""Set options and start addon."""
|
||||
"""Set options and start add-on."""
|
||||
if await self.instance.is_running():
|
||||
_LOGGER.warning("%s allready running!", self.slug)
|
||||
_LOGGER.warning("%s already running!", self.slug)
|
||||
return
|
||||
|
||||
# Access Token
|
||||
|
@ -724,7 +724,7 @@ class Addon(CoreSysAttributes):
|
|||
|
||||
@check_installed
|
||||
def stop(self):
|
||||
"""Stop addon.
|
||||
"""Stop add-on.
|
||||
|
||||
Return a coroutine.
|
||||
"""
|
||||
|
@ -732,11 +732,11 @@ class Addon(CoreSysAttributes):
|
|||
|
||||
@check_installed
|
||||
async def update(self):
|
||||
"""Update addon."""
|
||||
"""Update add-on."""
|
||||
last_state = await self.state()
|
||||
|
||||
if self.last_version == self.version_installed:
|
||||
_LOGGER.warning("No update available for Addon %s", self._id)
|
||||
_LOGGER.warning("No update available for add-on %s", self._id)
|
||||
return False
|
||||
|
||||
if not await self.instance.update(self.last_version):
|
||||
|
@ -753,13 +753,13 @@ class Addon(CoreSysAttributes):
|
|||
|
||||
@check_installed
|
||||
async def restart(self):
|
||||
"""Restart addon."""
|
||||
"""Restart add-on."""
|
||||
await self.stop()
|
||||
return await self.start()
|
||||
|
||||
@check_installed
|
||||
def logs(self):
|
||||
"""Return addons log output.
|
||||
"""Return add-ons log output.
|
||||
|
||||
Return a coroutine.
|
||||
"""
|
||||
|
@ -775,11 +775,11 @@ class Addon(CoreSysAttributes):
|
|||
|
||||
@check_installed
|
||||
async def rebuild(self):
|
||||
"""Performe a rebuild of local build addon."""
|
||||
"""Perform a rebuild of local build add-on."""
|
||||
last_state = await self.state()
|
||||
|
||||
if not self.need_build:
|
||||
_LOGGER.error("Can't rebuild a none local build addon!")
|
||||
_LOGGER.error("Can't rebuild a none local build add-on!")
|
||||
return False
|
||||
|
||||
# remove docker container but not addon config
|
||||
|
@ -808,7 +808,7 @@ class Addon(CoreSysAttributes):
|
|||
|
||||
@check_installed
|
||||
async def snapshot(self, tar_file):
|
||||
"""Snapshot state of an addon."""
|
||||
"""Snapshot state of an add-on."""
|
||||
with TemporaryDirectory(dir=str(self.sys_config.path_tmp)) as temp:
|
||||
# store local image
|
||||
if self.need_build and not await \
|
||||
|
@ -822,7 +822,7 @@ class Addon(CoreSysAttributes):
|
|||
ATTR_STATE: await self.state(),
|
||||
}
|
||||
|
||||
# store local configs/state
|
||||
# Store local configs/state
|
||||
try:
|
||||
write_json_file(Path(temp, 'addon.json'), data)
|
||||
except (OSError, json.JSONDecodeError) as err:
|
||||
|
@ -846,7 +846,7 @@ class Addon(CoreSysAttributes):
|
|||
snapshot.add(self.path_data, arcname="data")
|
||||
|
||||
try:
|
||||
_LOGGER.info("Build snapshot for addon %s", self._id)
|
||||
_LOGGER.info("Build snapshot for add-on %s", self._id)
|
||||
await self.sys_run_in_executor(_write_tarfile)
|
||||
except (tarfile.TarError, OSError) as err:
|
||||
_LOGGER.error("Can't write tarfile %s: %s", tar_file, err)
|
||||
|
@ -856,7 +856,7 @@ class Addon(CoreSysAttributes):
|
|||
return True
|
||||
|
||||
async def restore(self, tar_file):
|
||||
"""Restore state of an addon."""
|
||||
"""Restore state of an add-on."""
|
||||
with TemporaryDirectory(dir=str(self.sys_config.path_tmp)) as temp:
|
||||
# extract snapshot
|
||||
def _extract_tarfile():
|
||||
|
@ -870,13 +870,13 @@ class Addon(CoreSysAttributes):
|
|||
_LOGGER.error("Can't read tarfile %s: %s", tar_file, err)
|
||||
return False
|
||||
|
||||
# read snapshot data
|
||||
# Read snapshot data
|
||||
try:
|
||||
data = read_json_file(Path(temp, 'addon.json'))
|
||||
except (OSError, json.JSONDecodeError) as err:
|
||||
_LOGGER.error("Can't read addon.json: %s", err)
|
||||
|
||||
# validate
|
||||
# Validate
|
||||
try:
|
||||
data = SCHEMA_ADDON_SNAPSHOT(data)
|
||||
except vol.Invalid as err:
|
||||
|
@ -884,11 +884,11 @@ class Addon(CoreSysAttributes):
|
|||
self._id, humanize_error(data, err))
|
||||
return False
|
||||
|
||||
# restore data / reload addon
|
||||
# Restore data or reload add-on
|
||||
_LOGGER.info("Restore config for addon %s", self._id)
|
||||
self._restore_data(data[ATTR_USER], data[ATTR_SYSTEM])
|
||||
|
||||
# check version / restore image
|
||||
# Check version / restore image
|
||||
version = data[ATTR_VERSION]
|
||||
if not await self.instance.exists():
|
||||
_LOGGER.info("Restore image for addon %s", self._id)
|
||||
|
@ -902,7 +902,7 @@ class Addon(CoreSysAttributes):
|
|||
else:
|
||||
await self.instance.stop()
|
||||
|
||||
# restore data
|
||||
# Restore data
|
||||
def _restore_data():
|
||||
"""Restore data."""
|
||||
shutil.copytree(str(Path(temp, "data")), str(self.path_data))
|
||||
|
@ -926,9 +926,9 @@ class Addon(CoreSysAttributes):
|
|||
_LOGGER.error("Can't restore AppArmor profile")
|
||||
return False
|
||||
|
||||
# run addon
|
||||
# Run add-on
|
||||
if data[ATTR_STATE] == STATE_STARTED:
|
||||
return await self.start()
|
||||
|
||||
_LOGGER.info("Finish restore for addon %s", self._id)
|
||||
_LOGGER.info("Finish restore for add-on %s", self._id)
|
||||
return True
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""HassIO addons build environment."""
|
||||
"""Hass.io add-on build environment."""
|
||||
from pathlib import Path
|
||||
|
||||
from .validate import SCHEMA_BUILD_CONFIG, BASE_IMAGE
|
||||
|
@ -8,10 +8,10 @@ from ..utils.json import JsonConfig
|
|||
|
||||
|
||||
class AddonBuild(JsonConfig, CoreSysAttributes):
|
||||
"""Handle build options for addons."""
|
||||
"""Handle build options for add-ons."""
|
||||
|
||||
def __init__(self, coresys, slug):
|
||||
"""Initialize addon builder."""
|
||||
"""Initialize Hass.io add-on builder."""
|
||||
self.coresys = coresys
|
||||
self._id = slug
|
||||
|
||||
|
@ -24,12 +24,12 @@ class AddonBuild(JsonConfig, CoreSysAttributes):
|
|||
|
||||
@property
|
||||
def addon(self):
|
||||
"""Return addon of build data."""
|
||||
"""Return add-on of build data."""
|
||||
return self.sys_addons.get(self._id)
|
||||
|
||||
@property
|
||||
def base_image(self):
|
||||
"""Base images for this addon."""
|
||||
"""Base images for this add-on."""
|
||||
return self._data[ATTR_BUILD_FROM].get(
|
||||
self.sys_arch, BASE_IMAGE[self.sys_arch])
|
||||
|
||||
|
@ -40,11 +40,11 @@ class AddonBuild(JsonConfig, CoreSysAttributes):
|
|||
|
||||
@property
|
||||
def additional_args(self):
|
||||
"""Return additional docker build arguments."""
|
||||
"""Return additional Docker build arguments."""
|
||||
return self._data[ATTR_ARGS]
|
||||
|
||||
def get_docker_args(self, version):
|
||||
"""Create a dict with docker build arguments."""
|
||||
"""Create a dict with Docker build arguments."""
|
||||
args = {
|
||||
'path': str(self.addon.path_location),
|
||||
'tag': f"{self.addon.image}:{version}",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""Init file for HassIO addons."""
|
||||
"""Init file for Hass.io add-on data."""
|
||||
import logging
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
@ -19,7 +19,7 @@ _LOGGER = logging.getLogger(__name__)
|
|||
|
||||
|
||||
class AddonsData(JsonConfig, CoreSysAttributes):
|
||||
"""Hold data for addons inside HassIO."""
|
||||
"""Hold data for Add-ons inside Hass.io."""
|
||||
|
||||
def __init__(self, coresys):
|
||||
"""Initialize data holder."""
|
||||
|
@ -30,26 +30,26 @@ class AddonsData(JsonConfig, CoreSysAttributes):
|
|||
|
||||
@property
|
||||
def user(self):
|
||||
"""Return local addon user data."""
|
||||
"""Return local add-on user data."""
|
||||
return self._data[ATTR_USER]
|
||||
|
||||
@property
|
||||
def system(self):
|
||||
"""Return local addon data."""
|
||||
"""Return local add-on data."""
|
||||
return self._data[ATTR_SYSTEM]
|
||||
|
||||
@property
|
||||
def cache(self):
|
||||
"""Return addon data from cache/repositories."""
|
||||
"""Return add-on data from cache/repositories."""
|
||||
return self._cache
|
||||
|
||||
@property
|
||||
def repositories(self):
|
||||
"""Return addon data from repositories."""
|
||||
"""Return add-on data from repositories."""
|
||||
return self._repositories
|
||||
|
||||
def reload(self):
|
||||
"""Read data from addons repository."""
|
||||
"""Read data from add-on repository."""
|
||||
self._cache = {}
|
||||
self._repositories = {}
|
||||
|
||||
|
@ -94,7 +94,7 @@ class AddonsData(JsonConfig, CoreSysAttributes):
|
|||
self._read_addons_folder(path, slug)
|
||||
|
||||
def _read_addons_folder(self, path, repository):
|
||||
"""Read data from addons folder."""
|
||||
"""Read data from add-ons folder."""
|
||||
for addon in path.glob("**/config.json"):
|
||||
try:
|
||||
addon_config = read_json_file(addon)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""Init file for HassIO addons git."""
|
||||
"""Init file for Hass.io add-on Git."""
|
||||
import asyncio
|
||||
import logging
|
||||
import functools as ft
|
||||
|
@ -16,10 +16,10 @@ _LOGGER = logging.getLogger(__name__)
|
|||
|
||||
|
||||
class GitRepo(CoreSysAttributes):
|
||||
"""Manage addons git repo."""
|
||||
"""Manage Add-on Git repository."""
|
||||
|
||||
def __init__(self, coresys, path, url):
|
||||
"""Initialize git base wrapper."""
|
||||
"""Initialize Git base wrapper."""
|
||||
self.coresys = coresys
|
||||
self.repo = None
|
||||
self.path = path
|
||||
|
@ -38,13 +38,13 @@ class GitRepo(CoreSysAttributes):
|
|||
return self._data[ATTR_BRANCH]
|
||||
|
||||
async def load(self):
|
||||
"""Init git addon repo."""
|
||||
"""Init Git add-on repository."""
|
||||
if not self.path.is_dir():
|
||||
return await self.clone()
|
||||
|
||||
async with self.lock:
|
||||
try:
|
||||
_LOGGER.info("Load addon %s repository", self.path)
|
||||
_LOGGER.info("Load add-on %s repository", self.path)
|
||||
self.repo = await self.sys_run_in_executor(
|
||||
git.Repo, str(self.path))
|
||||
|
||||
|
@ -57,7 +57,7 @@ class GitRepo(CoreSysAttributes):
|
|||
return True
|
||||
|
||||
async def clone(self):
|
||||
"""Clone git addon repo."""
|
||||
"""Clone git add-on repository."""
|
||||
async with self.lock:
|
||||
git_args = {
|
||||
attribute: value
|
||||
|
@ -70,7 +70,7 @@ class GitRepo(CoreSysAttributes):
|
|||
}
|
||||
|
||||
try:
|
||||
_LOGGER.info("Clone addon %s repository", self.url)
|
||||
_LOGGER.info("Clone add-on %s repository", self.url)
|
||||
self.repo = await self.sys_run_in_executor(ft.partial(
|
||||
git.Repo.clone_from, self.url, str(self.path),
|
||||
**git_args
|
||||
|
@ -78,20 +78,20 @@ class GitRepo(CoreSysAttributes):
|
|||
|
||||
except (git.InvalidGitRepositoryError, git.NoSuchPathError,
|
||||
git.GitCommandError) as err:
|
||||
_LOGGER.error("Can't clone %s repo: %s.", self.url, err)
|
||||
_LOGGER.error("Can't clone %s repository: %s.", self.url, err)
|
||||
self._remove()
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
async def pull(self):
|
||||
"""Pull git addon repo."""
|
||||
"""Pull Git add-on repo."""
|
||||
if self.lock.locked():
|
||||
_LOGGER.warning("It is already a task in progress.")
|
||||
_LOGGER.warning("It is already a task in progress")
|
||||
return False
|
||||
|
||||
async with self.lock:
|
||||
_LOGGER.info("Update addon %s repository", self.url)
|
||||
_LOGGER.info("Update add-on %s repository", self.url)
|
||||
branch = self.repo.active_branch.name
|
||||
|
||||
try:
|
||||
|
@ -130,19 +130,19 @@ class GitRepo(CoreSysAttributes):
|
|||
|
||||
|
||||
class GitRepoHassIO(GitRepo):
|
||||
"""HassIO addons repository."""
|
||||
"""Hass.io add-ons repository."""
|
||||
|
||||
def __init__(self, coresys):
|
||||
"""Initialize git hassio addon repository."""
|
||||
"""Initialize Git Hass.io add-on repository."""
|
||||
super().__init__(
|
||||
coresys, coresys.config.path_addons_core, URL_HASSIO_ADDONS)
|
||||
|
||||
|
||||
class GitRepoCustom(GitRepo):
|
||||
"""Custom addons repository."""
|
||||
"""Custom add-ons repository."""
|
||||
|
||||
def __init__(self, coresys, url):
|
||||
"""Initialize git hassio addon repository."""
|
||||
"""Initialize custom Git Hass.io addo-n repository."""
|
||||
path = Path(
|
||||
coresys.config.path_addons_git,
|
||||
get_hash_from_repository(url))
|
||||
|
@ -151,5 +151,5 @@ class GitRepoCustom(GitRepo):
|
|||
|
||||
def remove(self):
|
||||
"""Remove a custom repository."""
|
||||
_LOGGER.info("Remove custom addon repository %s", self.url)
|
||||
_LOGGER.info("Remove custom add-on repository %s", self.url)
|
||||
self._remove()
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""Represent a HassIO repository."""
|
||||
"""Represent a Hass.io repository."""
|
||||
from .git import GitRepoHassIO, GitRepoCustom
|
||||
from .utils import get_hash_from_repository
|
||||
from ..const import (
|
||||
|
@ -9,7 +9,7 @@ UNKNOWN = 'unknown'
|
|||
|
||||
|
||||
class Repository(CoreSysAttributes):
|
||||
"""Repository in HassIO."""
|
||||
"""Repository in Hass.io."""
|
||||
|
||||
def __init__(self, coresys, repository):
|
||||
"""Initialize repository object."""
|
||||
|
@ -44,7 +44,7 @@ class Repository(CoreSysAttributes):
|
|||
|
||||
@property
|
||||
def url(self):
|
||||
"""Return url of repository."""
|
||||
"""Return URL of repository."""
|
||||
return self._mesh.get(ATTR_URL, self.source)
|
||||
|
||||
@property
|
||||
|
@ -59,13 +59,13 @@ class Repository(CoreSysAttributes):
|
|||
return True
|
||||
|
||||
async def update(self):
|
||||
"""Update addon repository."""
|
||||
"""Update add-on repository."""
|
||||
if self.git:
|
||||
return await self.git.pull()
|
||||
return True
|
||||
|
||||
def remove(self):
|
||||
"""Remove addon repository."""
|
||||
"""Remove add-on repository."""
|
||||
if self._id in (REPOSITORY_CORE, REPOSITORY_LOCAL):
|
||||
raise RuntimeError("Can't remove built-in repositories!")
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""Util addons functions."""
|
||||
"""Util add-ons functions."""
|
||||
import asyncio
|
||||
import hashlib
|
||||
import logging
|
||||
|
@ -78,7 +78,7 @@ def extract_hash_from_path(path):
|
|||
|
||||
|
||||
def check_installed(method):
|
||||
"""Wrap function with check if addon is installed."""
|
||||
"""Wrap function with check if add-on is installed."""
|
||||
async def wrap_check(addon, *args, **kwargs):
|
||||
"""Return False if not installed or the function."""
|
||||
if not addon.is_installed:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""Validate addons options schema."""
|
||||
"""Validate add-ons options schema."""
|
||||
import logging
|
||||
import re
|
||||
import uuid
|
||||
|
@ -218,7 +218,7 @@ SCHEMA_ADDON_SNAPSHOT = vol.Schema({
|
|||
def validate_options(raw_schema):
|
||||
"""Validate schema."""
|
||||
def validate(struct):
|
||||
"""Create schema validator for addons options."""
|
||||
"""Create schema validator for add-ons options."""
|
||||
options = {}
|
||||
|
||||
# read options
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""Init file for HassIO rest api."""
|
||||
"""Init file for Hass.io RESTful API."""
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
|
@ -21,10 +21,10 @@ _LOGGER = logging.getLogger(__name__)
|
|||
|
||||
|
||||
class RestAPI(CoreSysAttributes):
|
||||
"""Handle rest api for hassio."""
|
||||
"""Handle RESTful API for Hass.io."""
|
||||
|
||||
def __init__(self, coresys):
|
||||
"""Initialize docker base wrapper."""
|
||||
"""Initialize Docker base wrapper."""
|
||||
self.coresys = coresys
|
||||
self.security = SecurityMiddleware(coresys)
|
||||
self.webapp = web.Application(
|
||||
|
@ -49,7 +49,7 @@ class RestAPI(CoreSysAttributes):
|
|||
self._register_services()
|
||||
|
||||
def _register_host(self):
|
||||
"""Register hostcontrol function."""
|
||||
"""Register hostcontrol functions."""
|
||||
api_host = APIHost()
|
||||
api_host.coresys = self.coresys
|
||||
|
||||
|
@ -69,7 +69,7 @@ class RestAPI(CoreSysAttributes):
|
|||
])
|
||||
|
||||
def _register_hassos(self):
|
||||
"""Register hassos function."""
|
||||
"""Register HassOS functions."""
|
||||
api_hassos = APIHassOS()
|
||||
api_hassos.coresys = self.coresys
|
||||
|
||||
|
@ -81,7 +81,7 @@ class RestAPI(CoreSysAttributes):
|
|||
])
|
||||
|
||||
def _register_hardware(self):
|
||||
"""Register hardware function."""
|
||||
"""Register hardware functions."""
|
||||
api_hardware = APIHardware()
|
||||
api_hardware.coresys = self.coresys
|
||||
|
||||
|
@ -91,7 +91,7 @@ class RestAPI(CoreSysAttributes):
|
|||
])
|
||||
|
||||
def _register_supervisor(self):
|
||||
"""Register supervisor function."""
|
||||
"""Register Supervisor functions."""
|
||||
api_supervisor = APISupervisor()
|
||||
api_supervisor.coresys = self.coresys
|
||||
|
||||
|
@ -106,7 +106,7 @@ class RestAPI(CoreSysAttributes):
|
|||
])
|
||||
|
||||
def _register_homeassistant(self):
|
||||
"""Register homeassistant function."""
|
||||
"""Register Home Assistant functions."""
|
||||
api_hass = APIHomeAssistant()
|
||||
api_hass.coresys = self.coresys
|
||||
|
||||
|
@ -123,7 +123,7 @@ class RestAPI(CoreSysAttributes):
|
|||
])
|
||||
|
||||
def _register_proxy(self):
|
||||
"""Register HomeAssistant API Proxy."""
|
||||
"""Register Home Assistant API Proxy."""
|
||||
api_proxy = APIProxy()
|
||||
api_proxy.coresys = self.coresys
|
||||
|
||||
|
@ -137,7 +137,7 @@ class RestAPI(CoreSysAttributes):
|
|||
])
|
||||
|
||||
def _register_addons(self):
|
||||
"""Register homeassistant function."""
|
||||
"""Register Add-on functions."""
|
||||
api_addons = APIAddons()
|
||||
api_addons.coresys = self.coresys
|
||||
|
||||
|
@ -163,7 +163,7 @@ class RestAPI(CoreSysAttributes):
|
|||
])
|
||||
|
||||
def _register_snapshots(self):
|
||||
"""Register snapshots function."""
|
||||
"""Register snapshots functions."""
|
||||
api_snapshots = APISnapshots()
|
||||
api_snapshots.coresys = self.coresys
|
||||
|
||||
|
@ -183,6 +183,7 @@ class RestAPI(CoreSysAttributes):
|
|||
])
|
||||
|
||||
def _register_services(self):
|
||||
"""Register services functions."""
|
||||
api_services = APIServices()
|
||||
api_services.coresys = self.coresys
|
||||
|
||||
|
@ -194,6 +195,7 @@ class RestAPI(CoreSysAttributes):
|
|||
])
|
||||
|
||||
def _register_discovery(self):
|
||||
"""Register discovery functions."""
|
||||
api_discovery = APIDiscovery()
|
||||
api_discovery.coresys = self.coresys
|
||||
|
||||
|
@ -206,7 +208,7 @@ class RestAPI(CoreSysAttributes):
|
|||
])
|
||||
|
||||
def _register_panel(self):
|
||||
"""Register panel for homeassistant."""
|
||||
"""Register panel for Home Assistant."""
|
||||
panel_dir = Path(__file__).parent.joinpath("panel")
|
||||
|
||||
def create_response(panel_file):
|
||||
|
@ -234,7 +236,7 @@ class RestAPI(CoreSysAttributes):
|
|||
self.webapp.add_routes([web.static('/app', panel_dir)])
|
||||
|
||||
async def start(self):
|
||||
"""Run rest api webserver."""
|
||||
"""Run RESTful API webserver."""
|
||||
await self._runner.setup()
|
||||
self._site = web.TCPSite(
|
||||
self._runner, host="0.0.0.0", port=80, shutdown_timeout=5)
|
||||
|
@ -248,7 +250,7 @@ class RestAPI(CoreSysAttributes):
|
|||
_LOGGER.info("Start API on %s", self.sys_docker.network.supervisor)
|
||||
|
||||
async def stop(self):
|
||||
"""Stop rest api webserver."""
|
||||
"""Stop RESTful API webserver."""
|
||||
if not self._site:
|
||||
return
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""Init file for HassIO homeassistant rest api."""
|
||||
"""Init file for Hass.io Home Assistant RESTful API."""
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
|
@ -48,7 +48,7 @@ SCHEMA_SECURITY = vol.Schema({
|
|||
|
||||
|
||||
class APIAddons(CoreSysAttributes):
|
||||
"""Handle rest api for addons functions."""
|
||||
"""Handle RESTful API for add-on functions."""
|
||||
|
||||
def _extract_addon(self, request, check_installed=True):
|
||||
"""Return addon, throw an exception it it doesn't exist."""
|
||||
|
@ -77,7 +77,7 @@ class APIAddons(CoreSysAttributes):
|
|||
|
||||
@api_process
|
||||
async def list(self, request):
|
||||
"""Return all addons / repositories ."""
|
||||
"""Return all add-ons or repositories."""
|
||||
data_addons = []
|
||||
for addon in self.sys_addons.list_addons:
|
||||
data_addons.append({
|
||||
|
@ -112,13 +112,13 @@ class APIAddons(CoreSysAttributes):
|
|||
|
||||
@api_process
|
||||
async def reload(self, request):
|
||||
"""Reload all addons data."""
|
||||
"""Reload all add-on data."""
|
||||
await asyncio.shield(self.sys_addons.reload())
|
||||
return True
|
||||
|
||||
@api_process
|
||||
async def info(self, request):
|
||||
"""Return addon information."""
|
||||
"""Return add-on information."""
|
||||
addon = self._extract_addon(request, check_installed=False)
|
||||
|
||||
return {
|
||||
|
@ -167,7 +167,7 @@ class APIAddons(CoreSysAttributes):
|
|||
|
||||
@api_process
|
||||
async def options(self, request):
|
||||
"""Store user options for addon."""
|
||||
"""Store user options for add-on."""
|
||||
addon = self._extract_addon(request)
|
||||
|
||||
addon_schema = SCHEMA_OPTIONS.extend({
|
||||
|
@ -194,7 +194,7 @@ class APIAddons(CoreSysAttributes):
|
|||
|
||||
@api_process
|
||||
async def security(self, request):
|
||||
"""Store security options for addon."""
|
||||
"""Store security options for add-on."""
|
||||
addon = self._extract_addon(request)
|
||||
|
||||
# Have Access
|
||||
|
@ -233,19 +233,19 @@ class APIAddons(CoreSysAttributes):
|
|||
|
||||
@api_process
|
||||
def install(self, request):
|
||||
"""Install addon."""
|
||||
"""Install add-on."""
|
||||
addon = self._extract_addon(request, check_installed=False)
|
||||
return asyncio.shield(addon.install())
|
||||
|
||||
@api_process
|
||||
def uninstall(self, request):
|
||||
"""Uninstall addon."""
|
||||
"""Uninstall add-on."""
|
||||
addon = self._extract_addon(request)
|
||||
return asyncio.shield(addon.uninstall())
|
||||
|
||||
@api_process
|
||||
def start(self, request):
|
||||
"""Start addon."""
|
||||
"""Start add-on."""
|
||||
addon = self._extract_addon(request)
|
||||
|
||||
# check options
|
||||
|
@ -259,13 +259,13 @@ class APIAddons(CoreSysAttributes):
|
|||
|
||||
@api_process
|
||||
def stop(self, request):
|
||||
"""Stop addon."""
|
||||
"""Stop add-on."""
|
||||
addon = self._extract_addon(request)
|
||||
return asyncio.shield(addon.stop())
|
||||
|
||||
@api_process
|
||||
def update(self, request):
|
||||
"""Update addon."""
|
||||
"""Update add-on."""
|
||||
addon = self._extract_addon(request)
|
||||
|
||||
if addon.last_version == addon.version_installed:
|
||||
|
@ -275,13 +275,13 @@ class APIAddons(CoreSysAttributes):
|
|||
|
||||
@api_process
|
||||
def restart(self, request):
|
||||
"""Restart addon."""
|
||||
"""Restart add-on."""
|
||||
addon = self._extract_addon(request)
|
||||
return asyncio.shield(addon.restart())
|
||||
|
||||
@api_process
|
||||
def rebuild(self, request):
|
||||
"""Rebuild local build addon."""
|
||||
"""Rebuild local build add-on."""
|
||||
addon = self._extract_addon(request)
|
||||
if not addon.need_build:
|
||||
raise RuntimeError("Only local build addons are supported")
|
||||
|
@ -290,13 +290,13 @@ class APIAddons(CoreSysAttributes):
|
|||
|
||||
@api_process_raw(CONTENT_TYPE_BINARY)
|
||||
def logs(self, request):
|
||||
"""Return logs from addon."""
|
||||
"""Return logs from add-on."""
|
||||
addon = self._extract_addon(request)
|
||||
return addon.logs()
|
||||
|
||||
@api_process_raw(CONTENT_TYPE_PNG)
|
||||
async def icon(self, request):
|
||||
"""Return icon from addon."""
|
||||
"""Return icon from add-on."""
|
||||
addon = self._extract_addon(request, check_installed=False)
|
||||
if not addon.with_icon:
|
||||
raise RuntimeError("No icon found!")
|
||||
|
@ -306,7 +306,7 @@ class APIAddons(CoreSysAttributes):
|
|||
|
||||
@api_process_raw(CONTENT_TYPE_PNG)
|
||||
async def logo(self, request):
|
||||
"""Return logo from addon."""
|
||||
"""Return logo from add-on."""
|
||||
addon = self._extract_addon(request, check_installed=False)
|
||||
if not addon.with_logo:
|
||||
raise RuntimeError("No logo found!")
|
||||
|
@ -316,7 +316,7 @@ class APIAddons(CoreSysAttributes):
|
|||
|
||||
@api_process_raw(CONTENT_TYPE_TEXT)
|
||||
async def changelog(self, request):
|
||||
"""Return changelog from addon."""
|
||||
"""Return changelog from add-on."""
|
||||
addon = self._extract_addon(request, check_installed=False)
|
||||
if not addon.with_changelog:
|
||||
raise RuntimeError("No changelog found!")
|
||||
|
@ -326,10 +326,10 @@ class APIAddons(CoreSysAttributes):
|
|||
|
||||
@api_process
|
||||
async def stdin(self, request):
|
||||
"""Write to stdin of addon."""
|
||||
"""Write to stdin of add-on."""
|
||||
addon = self._extract_addon(request)
|
||||
if not addon.with_stdin:
|
||||
raise RuntimeError("STDIN not supported by addon")
|
||||
raise RuntimeError("STDIN not supported by add-on")
|
||||
|
||||
data = await request.read()
|
||||
return await asyncio.shield(addon.write_stdin(data))
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
"""Init file for HassIO network rest api."""
|
||||
|
||||
"""Init file for Hass.io network RESTful API."""
|
||||
import voluptuous as vol
|
||||
|
||||
from .utils import api_process, api_validate
|
||||
|
@ -17,7 +16,7 @@ SCHEMA_DISCOVERY = vol.Schema({
|
|||
|
||||
|
||||
class APIDiscovery(CoreSysAttributes):
|
||||
"""Handle rest api for discovery functions."""
|
||||
"""Handle RESTful API for discovery functions."""
|
||||
|
||||
def _extract_message(self, request):
|
||||
"""Extract discovery message from URL."""
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""Init file for HassIO hardware rest api."""
|
||||
"""Init file for Hass.io hardware RESTful API."""
|
||||
import logging
|
||||
|
||||
from .utils import api_process
|
||||
|
@ -10,7 +10,7 @@ _LOGGER = logging.getLogger(__name__)
|
|||
|
||||
|
||||
class APIHardware(CoreSysAttributes):
|
||||
"""Handle rest api for hardware functions."""
|
||||
"""Handle RESTful API for hardware functions."""
|
||||
|
||||
@api_process
|
||||
async def info(self, request):
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""Init file for Hass.io hassos rest api."""
|
||||
"""Init file for Hass.io HassOS RESTful API."""
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
|
@ -18,11 +18,11 @@ SCHEMA_VERSION = vol.Schema({
|
|||
|
||||
|
||||
class APIHassOS(CoreSysAttributes):
|
||||
"""Handle rest api for hassos functions."""
|
||||
"""Handle RESTful API for HassOS functions."""
|
||||
|
||||
@api_process
|
||||
async def info(self, request):
|
||||
"""Return hassos information."""
|
||||
"""Return HassOS information."""
|
||||
return {
|
||||
ATTR_VERSION: self.sys_hassos.version,
|
||||
ATTR_VERSION_CLI: self.sys_hassos.version_cli,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""Init file for HassIO homeassistant rest api."""
|
||||
"""Init file for Hass.io Home Assistant RESTful API."""
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
|
@ -39,7 +39,7 @@ SCHEMA_VERSION = vol.Schema({
|
|||
|
||||
|
||||
class APIHomeAssistant(CoreSysAttributes):
|
||||
"""Handle rest api for homeassistant functions."""
|
||||
"""Handle RESTful API for Home Assistant functions."""
|
||||
|
||||
@api_process
|
||||
async def info(self, request):
|
||||
|
@ -59,7 +59,7 @@ class APIHomeAssistant(CoreSysAttributes):
|
|||
|
||||
@api_process
|
||||
async def options(self, request):
|
||||
"""Set homeassistant options."""
|
||||
"""Set Home Assistant options."""
|
||||
body = await api_validate(SCHEMA_OPTIONS, request)
|
||||
|
||||
if ATTR_IMAGE in body and ATTR_LAST_VERSION in body:
|
||||
|
@ -108,7 +108,7 @@ class APIHomeAssistant(CoreSysAttributes):
|
|||
|
||||
@api_process
|
||||
async def update(self, request):
|
||||
"""Update homeassistant."""
|
||||
"""Update Home Assistant."""
|
||||
body = await api_validate(SCHEMA_VERSION, request)
|
||||
version = body.get(ATTR_VERSION, self.sys_homeassistant.last_version)
|
||||
|
||||
|
@ -116,27 +116,27 @@ class APIHomeAssistant(CoreSysAttributes):
|
|||
|
||||
@api_process
|
||||
def stop(self, request):
|
||||
"""Stop homeassistant."""
|
||||
"""Stop Home Assistant."""
|
||||
return asyncio.shield(self.sys_homeassistant.stop())
|
||||
|
||||
@api_process
|
||||
def start(self, request):
|
||||
"""Start homeassistant."""
|
||||
"""Start Home Assistant."""
|
||||
return asyncio.shield(self.sys_homeassistant.start())
|
||||
|
||||
@api_process
|
||||
def restart(self, request):
|
||||
"""Restart homeassistant."""
|
||||
"""Restart Home Assistant."""
|
||||
return asyncio.shield(self.sys_homeassistant.restart())
|
||||
|
||||
@api_process_raw(CONTENT_TYPE_BINARY)
|
||||
def logs(self, request):
|
||||
"""Return homeassistant docker logs."""
|
||||
"""Return Home Assistant Docker logs."""
|
||||
return self.sys_homeassistant.logs()
|
||||
|
||||
@api_process
|
||||
async def check(self, request):
|
||||
"""Check config of homeassistant."""
|
||||
"""Check configuration of Home Assistant."""
|
||||
result = await self.sys_homeassistant.check_config()
|
||||
if not result.valid:
|
||||
raise RuntimeError(result.log)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""Init file for HassIO host rest api."""
|
||||
"""Init file for Hass.io host RESTful API."""
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
|
@ -21,7 +21,7 @@ SCHEMA_OPTIONS = vol.Schema({
|
|||
|
||||
|
||||
class APIHost(CoreSysAttributes):
|
||||
"""Handle rest api for host functions."""
|
||||
"""Handle RESTful API for host functions."""
|
||||
|
||||
@api_process
|
||||
async def info(self, request):
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""Utils for HomeAssistant Proxy."""
|
||||
"""Utils for Home Assistant Proxy."""
|
||||
import asyncio
|
||||
from contextlib import asynccontextmanager
|
||||
import logging
|
||||
|
@ -18,7 +18,7 @@ _LOGGER = logging.getLogger(__name__)
|
|||
|
||||
|
||||
class APIProxy(CoreSysAttributes):
|
||||
"""API Proxy for Home-Assistant."""
|
||||
"""API Proxy for Home Assistant."""
|
||||
|
||||
def _check_access(self, request):
|
||||
"""Check the Hass.io token."""
|
||||
|
@ -30,7 +30,7 @@ class APIProxy(CoreSysAttributes):
|
|||
addon = self.sys_addons.from_uuid(hassio_token)
|
||||
|
||||
if not addon:
|
||||
_LOGGER.warning("Unknown HomeAssistant API access!")
|
||||
_LOGGER.warning("Unknown Home Assistant API access!")
|
||||
elif not addon.access_homeassistant_api:
|
||||
_LOGGER.warning("Not permitted API access: %s", addon.slug)
|
||||
else:
|
||||
|
@ -41,7 +41,7 @@ class APIProxy(CoreSysAttributes):
|
|||
|
||||
@asynccontextmanager
|
||||
async def _api_client(self, request, path, timeout=300):
|
||||
"""Return a client request with proxy origin for Home-Assistant."""
|
||||
"""Return a client request with proxy origin for Home Assistant."""
|
||||
try:
|
||||
# read data
|
||||
with async_timeout.timeout(30):
|
||||
|
@ -76,7 +76,7 @@ class APIProxy(CoreSysAttributes):
|
|||
"""Proxy HomeAssistant EventStream Requests."""
|
||||
self._check_access(request)
|
||||
|
||||
_LOGGER.info("Home-Assistant EventStream start")
|
||||
_LOGGER.info("Home Assistant EventStream start")
|
||||
async with self._api_client(request, 'stream', timeout=None) as client:
|
||||
response = web.StreamResponse()
|
||||
response.content_type = request.headers.get(CONTENT_TYPE)
|
||||
|
@ -93,12 +93,12 @@ class APIProxy(CoreSysAttributes):
|
|||
|
||||
finally:
|
||||
client.close()
|
||||
_LOGGER.info("Home-Assistant EventStream close")
|
||||
_LOGGER.info("Home Assistant EventStream close")
|
||||
|
||||
return response
|
||||
|
||||
async def api(self, request):
|
||||
"""Proxy HomeAssistant API Requests."""
|
||||
"""Proxy Home Assistant API Requests."""
|
||||
self._check_access(request)
|
||||
|
||||
# Normal request
|
||||
|
@ -112,14 +112,14 @@ class APIProxy(CoreSysAttributes):
|
|||
)
|
||||
|
||||
async def _websocket_client(self):
|
||||
"""Initialize a websocket api connection."""
|
||||
"""Initialize a WebSocket API connection."""
|
||||
url = f"{self.sys_homeassistant.api_url}/api/websocket"
|
||||
|
||||
try:
|
||||
client = await self.sys_websession_ssl.ws_connect(
|
||||
url, heartbeat=60, verify_ssl=False)
|
||||
|
||||
# handle authentication
|
||||
# Handle authentication
|
||||
data = await client.receive_json()
|
||||
|
||||
if data.get('type') == 'auth_ok':
|
||||
|
@ -128,7 +128,7 @@ class APIProxy(CoreSysAttributes):
|
|||
if data.get('type') != 'auth_required':
|
||||
# Invalid protocol
|
||||
_LOGGER.error(
|
||||
'Got unexpected response from HA websocket: %s', data)
|
||||
"Got unexpected response from HA WebSocket: %s", data)
|
||||
raise HTTPBadGateway()
|
||||
|
||||
if self.sys_homeassistant.refresh_token:
|
||||
|
@ -157,15 +157,15 @@ class APIProxy(CoreSysAttributes):
|
|||
raise HomeAssistantAuthError()
|
||||
|
||||
except (RuntimeError, ValueError) as err:
|
||||
_LOGGER.error("Client error on websocket API %s.", err)
|
||||
_LOGGER.error("Client error on WebSocket API %s.", err)
|
||||
except HomeAssistantAuthError as err:
|
||||
_LOGGER.error("Failed authentication to HomeAssistant websocket")
|
||||
_LOGGER.error("Failed authentication to Home Assistant WebSocket")
|
||||
|
||||
raise HTTPBadGateway()
|
||||
|
||||
async def websocket(self, request):
|
||||
"""Initialize a websocket api connection."""
|
||||
_LOGGER.info("Home-Assistant Websocket API request initialze")
|
||||
"""Initialize a WebSocket API connection."""
|
||||
_LOGGER.info("Home Assistant WebSocket API request initialize")
|
||||
|
||||
# init server
|
||||
server = web.WebSocketResponse(heartbeat=60)
|
||||
|
@ -189,14 +189,14 @@ class APIProxy(CoreSysAttributes):
|
|||
addon = self.sys_addons.from_uuid(hassio_token)
|
||||
|
||||
if not addon or not addon.access_homeassistant_api:
|
||||
_LOGGER.warning("Unauthorized websocket access!")
|
||||
_LOGGER.warning("Unauthorized WebSocket access!")
|
||||
await server.send_json({
|
||||
'type': 'auth_invalid',
|
||||
'message': 'Invalid access',
|
||||
})
|
||||
return server
|
||||
|
||||
_LOGGER.info("Websocket access from %s", addon.slug)
|
||||
_LOGGER.info("WebSocket access from %s", addon.slug)
|
||||
|
||||
await server.send_json({
|
||||
'type': 'auth_ok',
|
||||
|
@ -209,7 +209,7 @@ class APIProxy(CoreSysAttributes):
|
|||
# init connection to hass
|
||||
client = await self._websocket_client()
|
||||
|
||||
_LOGGER.info("Home-Assistant Websocket API request running")
|
||||
_LOGGER.info("Home Assistant WebSocket API request running")
|
||||
try:
|
||||
client_read = None
|
||||
server_read = None
|
||||
|
@ -243,7 +243,7 @@ class APIProxy(CoreSysAttributes):
|
|||
pass
|
||||
|
||||
except RuntimeError as err:
|
||||
_LOGGER.info("Home-Assistant Websocket API error: %s", err)
|
||||
_LOGGER.info("Home Assistant WebSocket API error: %s", err)
|
||||
|
||||
finally:
|
||||
if client_read:
|
||||
|
@ -255,5 +255,5 @@ class APIProxy(CoreSysAttributes):
|
|||
await client.close()
|
||||
await server.close()
|
||||
|
||||
_LOGGER.info("Home-Assistant Websocket API connection is closed")
|
||||
_LOGGER.info("Home Assistant WebSocket API connection is closed")
|
||||
return server
|
||||
|
|
|
@ -88,7 +88,7 @@ class SecurityMiddleware(CoreSysAttributes):
|
|||
# UUID check need removed with 131
|
||||
if hassio_token in (self.sys_homeassistant.uuid,
|
||||
self.sys_homeassistant.hassio_token):
|
||||
_LOGGER.debug("%s access from Home-Assistant", request.path)
|
||||
_LOGGER.debug("%s access from Home Assistant", request.path)
|
||||
request_from = 'homeassistant'
|
||||
|
||||
# Host
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""Init file for HassIO network rest api."""
|
||||
"""Init file for Hass.io network RESTful API."""
|
||||
|
||||
from .utils import api_process, api_validate
|
||||
from ..const import (
|
||||
|
@ -7,7 +7,7 @@ from ..coresys import CoreSysAttributes
|
|||
|
||||
|
||||
class APIServices(CoreSysAttributes):
|
||||
"""Handle rest api for services functions."""
|
||||
"""Handle RESTful API for services functions."""
|
||||
|
||||
def _extract_service(self, request):
|
||||
"""Return service, throw an exception if it doesn't exist."""
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""Init file for HassIO snapshot rest api."""
|
||||
"""Init file for Hass.io snapshot RESTful API."""
|
||||
import asyncio
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
@ -46,7 +46,7 @@ SCHEMA_SNAPSHOT_PARTIAL = SCHEMA_SNAPSHOT_FULL.extend({
|
|||
|
||||
|
||||
class APISnapshots(CoreSysAttributes):
|
||||
"""Handle rest api for snapshot functions."""
|
||||
"""Handle RESTful API for snapshot functions."""
|
||||
|
||||
def _extract_snapshot(self, request):
|
||||
"""Return snapshot, throw an exception if it doesn't exist."""
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""Init file for HassIO supervisor rest api."""
|
||||
"""Init file for Hass.io Supervisor RESTful API."""
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
|
@ -30,11 +30,11 @@ SCHEMA_VERSION = vol.Schema({
|
|||
|
||||
|
||||
class APISupervisor(CoreSysAttributes):
|
||||
"""Handle rest api for supervisor functions."""
|
||||
"""Handle RESTful API for Supervisor functions."""
|
||||
|
||||
@api_process
|
||||
async def ping(self, request):
|
||||
"""Return ok for signal that the api is ready."""
|
||||
"""Return ok for signal that the API is ready."""
|
||||
return True
|
||||
|
||||
@api_process
|
||||
|
@ -68,7 +68,7 @@ class APISupervisor(CoreSysAttributes):
|
|||
|
||||
@api_process
|
||||
async def options(self, request):
|
||||
"""Set supervisor options."""
|
||||
"""Set Supervisor options."""
|
||||
body = await api_validate(SCHEMA_OPTIONS, request)
|
||||
|
||||
if ATTR_CHANNEL in body:
|
||||
|
@ -107,7 +107,7 @@ class APISupervisor(CoreSysAttributes):
|
|||
|
||||
@api_process
|
||||
async def update(self, request):
|
||||
"""Update supervisor OS."""
|
||||
"""Update Supervisor OS."""
|
||||
body = await api_validate(SCHEMA_VERSION, request)
|
||||
version = body.get(ATTR_VERSION, self.sys_updater.version_hassio)
|
||||
|
||||
|
@ -119,7 +119,7 @@ class APISupervisor(CoreSysAttributes):
|
|||
|
||||
@api_process
|
||||
async def reload(self, request):
|
||||
"""Reload addons, config etc."""
|
||||
"""Reload add-ons, configuration, etc."""
|
||||
tasks = [
|
||||
self.sys_updater.reload(),
|
||||
]
|
||||
|
@ -134,5 +134,5 @@ class APISupervisor(CoreSysAttributes):
|
|||
|
||||
@api_process_raw(CONTENT_TYPE_BINARY)
|
||||
def logs(self, request):
|
||||
"""Return supervisor docker logs."""
|
||||
"""Return supervisor Docker logs."""
|
||||
return self.sys_supervisor.logs()
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""Init file for HassIO util for rest api."""
|
||||
"""Init file for Hass.io util for RESTful API."""
|
||||
import json
|
||||
import logging
|
||||
|
||||
|
@ -27,7 +27,7 @@ def json_loads(data):
|
|||
def api_process(method):
|
||||
"""Wrap function with true/false calls to rest api."""
|
||||
async def wrap_api(api, *args, **kwargs):
|
||||
"""Return api information."""
|
||||
"""Return API information."""
|
||||
try:
|
||||
answer = await method(api, *args, **kwargs)
|
||||
except HassioError:
|
||||
|
|
|
@ -16,7 +16,7 @@ class Systemd(DBusInterface):
|
|||
"""Systemd function handler."""
|
||||
|
||||
async def connect(self):
|
||||
"""Connect do bus."""
|
||||
"""Connect to D-Bus."""
|
||||
try:
|
||||
self.dbus = await DBus.connect(DBUS_NAME, DBUS_OBJECT)
|
||||
except DBusError:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""Init file for HassIO docker object."""
|
||||
"""Init file for Hass.io Docker object."""
|
||||
from contextlib import suppress
|
||||
import logging
|
||||
|
||||
|
@ -15,13 +15,13 @@ CommandReturn = attr.make_class('CommandReturn', ['exit_code', 'output'])
|
|||
|
||||
|
||||
class DockerAPI:
|
||||
"""Docker hassio wrapper.
|
||||
"""Docker Hass.io wrapper.
|
||||
|
||||
This class is not AsyncIO safe!
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize docker base wrapper."""
|
||||
"""Initialize Docker base wrapper."""
|
||||
self.docker = docker.DockerClient(
|
||||
base_url="unix:/{}".format(str(SOCKET_DOCKER)),
|
||||
version='auto', timeout=900)
|
||||
|
@ -29,21 +29,21 @@ class DockerAPI:
|
|||
|
||||
@property
|
||||
def images(self):
|
||||
"""Return api images."""
|
||||
"""Return API images."""
|
||||
return self.docker.images
|
||||
|
||||
@property
|
||||
def containers(self):
|
||||
"""Return api containers."""
|
||||
"""Return API containers."""
|
||||
return self.docker.containers
|
||||
|
||||
@property
|
||||
def api(self):
|
||||
"""Return api containers."""
|
||||
"""Return API containers."""
|
||||
return self.docker.api
|
||||
|
||||
def run(self, image, **kwargs):
|
||||
""""Create a docker and run it.
|
||||
""""Create a Docker container and run it.
|
||||
|
||||
Need run inside executor.
|
||||
"""
|
||||
|
@ -51,7 +51,7 @@ class DockerAPI:
|
|||
network_mode = kwargs.get('network_mode')
|
||||
hostname = kwargs.get('hostname')
|
||||
|
||||
# setup network
|
||||
# Setup network
|
||||
kwargs['dns_search'] = ["."]
|
||||
if network_mode:
|
||||
kwargs['dns'] = [str(self.network.supervisor)]
|
||||
|
@ -59,7 +59,7 @@ class DockerAPI:
|
|||
else:
|
||||
kwargs['network'] = None
|
||||
|
||||
# create container
|
||||
# Create container
|
||||
try:
|
||||
container = self.docker.containers.create(image, **kwargs)
|
||||
except docker.errors.DockerException as err:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""Init file for HassIO addon docker object."""
|
||||
"""Init file for Hass.io add-on Docker object."""
|
||||
import logging
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
@ -19,45 +19,45 @@ AUDIO_DEVICE = "/dev/snd:/dev/snd:rwm"
|
|||
|
||||
|
||||
class DockerAddon(DockerInterface):
|
||||
"""Docker hassio wrapper for HomeAssistant."""
|
||||
"""Docker Hass.io wrapper for Home Assistant."""
|
||||
|
||||
def __init__(self, coresys, slug):
|
||||
"""Initialize docker homeassistant wrapper."""
|
||||
"""Initialize Docker Home Assistant wrapper."""
|
||||
super().__init__(coresys)
|
||||
self._id = slug
|
||||
|
||||
@property
|
||||
def addon(self):
|
||||
"""Return addon of docker image."""
|
||||
"""Return add-on of Docker image."""
|
||||
return self.sys_addons.get(self._id)
|
||||
|
||||
@property
|
||||
def image(self):
|
||||
"""Return name of docker image."""
|
||||
"""Return name of Docker image."""
|
||||
return self.addon.image
|
||||
|
||||
@property
|
||||
def timeout(self):
|
||||
"""Return timeout for docker actions."""
|
||||
"""Return timeout for Docker actions."""
|
||||
return self.addon.timeout
|
||||
|
||||
@property
|
||||
def version(self):
|
||||
"""Return version of docker image."""
|
||||
"""Return version of Docker image."""
|
||||
if not self.addon.legacy:
|
||||
return super().version
|
||||
return self.addon.version_installed
|
||||
|
||||
@property
|
||||
def arch(self):
|
||||
"""Return arch of docker image."""
|
||||
"""Return arch of Docker image."""
|
||||
if not self.addon.legacy:
|
||||
return super().arch
|
||||
return self.sys_arch
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return name of docker container."""
|
||||
"""Return name of Docker container."""
|
||||
return "addon_{}".format(self.addon.slug)
|
||||
|
||||
@property
|
||||
|
@ -74,12 +74,12 @@ class DockerAddon(DockerInterface):
|
|||
|
||||
@property
|
||||
def hostname(self):
|
||||
"""Return slug/id of addon."""
|
||||
"""Return slug/id of add-on."""
|
||||
return self.addon.slug.replace('_', '-')
|
||||
|
||||
@property
|
||||
def environment(self):
|
||||
"""Return environment for docker add-on."""
|
||||
"""Return environment for Docker add-on."""
|
||||
addon_env = self.addon.environment or {}
|
||||
|
||||
# Need audio settings
|
||||
|
@ -114,7 +114,7 @@ class DockerAddon(DockerInterface):
|
|||
|
||||
@property
|
||||
def ports(self):
|
||||
"""Filter None from addon ports."""
|
||||
"""Filter None from add-on ports."""
|
||||
if not self.addon.ports:
|
||||
return None
|
||||
|
||||
|
@ -126,7 +126,7 @@ class DockerAddon(DockerInterface):
|
|||
|
||||
@property
|
||||
def security_opt(self):
|
||||
"""Controlling security opt."""
|
||||
"""Controlling security options."""
|
||||
security = []
|
||||
|
||||
# AppArmor
|
||||
|
@ -144,7 +144,7 @@ class DockerAddon(DockerInterface):
|
|||
|
||||
@property
|
||||
def tmpfs(self):
|
||||
"""Return tmpfs for docker add-on."""
|
||||
"""Return tmpfs for Docker add-on."""
|
||||
options = self.addon.tmpfs
|
||||
if options:
|
||||
return {"/tmpfs": f"{options}"}
|
||||
|
@ -160,14 +160,14 @@ class DockerAddon(DockerInterface):
|
|||
|
||||
@property
|
||||
def network_mode(self):
|
||||
"""Return network mode for addon."""
|
||||
"""Return network mode for add-on."""
|
||||
if self.addon.host_network:
|
||||
return 'host'
|
||||
return None
|
||||
|
||||
@property
|
||||
def pid_mode(self):
|
||||
"""Return PID mode for addon."""
|
||||
"""Return PID mode for add-on."""
|
||||
if not self.addon.protected and self.addon.host_pid:
|
||||
return 'host'
|
||||
return None
|
||||
|
@ -242,7 +242,7 @@ class DockerAddon(DockerInterface):
|
|||
},
|
||||
})
|
||||
|
||||
# Host dbus system
|
||||
# Host D-Bus system
|
||||
if self.addon.host_dbus:
|
||||
volumes.update({
|
||||
"/var/run/dbus": {
|
||||
|
@ -259,7 +259,7 @@ class DockerAddon(DockerInterface):
|
|||
return volumes
|
||||
|
||||
def _run(self):
|
||||
"""Run docker image.
|
||||
"""Run Docker image.
|
||||
|
||||
Need run inside executor.
|
||||
"""
|
||||
|
@ -269,7 +269,7 @@ class DockerAddon(DockerInterface):
|
|||
# Security check
|
||||
if not self.addon.protected:
|
||||
_LOGGER.warning(
|
||||
"%s run with disabled proteced mode!", self.addon.name)
|
||||
"%s run with disabled protected mode!", self.addon.name)
|
||||
|
||||
# cleanup
|
||||
self._stop()
|
||||
|
@ -296,13 +296,13 @@ class DockerAddon(DockerInterface):
|
|||
)
|
||||
|
||||
if ret:
|
||||
_LOGGER.info("Start docker addon %s with version %s",
|
||||
_LOGGER.info("Start Docker add-on %s with version %s",
|
||||
self.image, self.version)
|
||||
|
||||
return ret
|
||||
|
||||
def _install(self, tag):
|
||||
"""Pull docker image or build it.
|
||||
"""Pull Docker image or build it.
|
||||
|
||||
Need run inside executor.
|
||||
"""
|
||||
|
@ -312,7 +312,7 @@ class DockerAddon(DockerInterface):
|
|||
return super()._install(tag)
|
||||
|
||||
def _build(self, tag):
|
||||
"""Build a docker container.
|
||||
"""Build a Docker container.
|
||||
|
||||
Need run inside executor.
|
||||
"""
|
||||
|
@ -329,7 +329,7 @@ class DockerAddon(DockerInterface):
|
|||
# Update meta data
|
||||
self._meta = image.attrs
|
||||
|
||||
except (docker.errors.DockerException) as err:
|
||||
except docker.errors.DockerException as err:
|
||||
_LOGGER.error("Can't build %s:%s: %s", self.image, tag, err)
|
||||
return False
|
||||
|
||||
|
@ -403,7 +403,7 @@ class DockerAddon(DockerInterface):
|
|||
return False
|
||||
|
||||
try:
|
||||
# load needed docker objects
|
||||
# Load needed docker objects
|
||||
container = self.sys_docker.containers.get(self.name)
|
||||
socket = container.attach_socket(params={'stdin': 1, 'stream': 1})
|
||||
except docker.errors.DockerException as err:
|
||||
|
@ -411,7 +411,7 @@ class DockerAddon(DockerInterface):
|
|||
return False
|
||||
|
||||
try:
|
||||
# write to stdin
|
||||
# Write to stdin
|
||||
data += b"\n"
|
||||
os.write(socket.fileno(), data)
|
||||
socket.close()
|
||||
|
|
|
@ -10,11 +10,11 @@ _LOGGER = logging.getLogger(__name__)
|
|||
|
||||
|
||||
class DockerHassOSCli(DockerInterface, CoreSysAttributes):
|
||||
"""Docker hassio wrapper for HassOS Cli."""
|
||||
"""Docker Hass.io wrapper for HassOS Cli."""
|
||||
|
||||
@property
|
||||
def image(self):
|
||||
"""Return name of HassOS cli image."""
|
||||
"""Return name of HassOS CLI image."""
|
||||
return f"homeassistant/{self.sys_arch}-hassio-cli"
|
||||
|
||||
def _stop(self):
|
||||
|
@ -22,16 +22,16 @@ class DockerHassOSCli(DockerInterface, CoreSysAttributes):
|
|||
return True
|
||||
|
||||
def _attach(self):
|
||||
"""Attach to running docker container.
|
||||
"""Attach to running Docker container.
|
||||
Need run inside executor.
|
||||
"""
|
||||
try:
|
||||
image = self.sys_docker.images.get(self.image)
|
||||
|
||||
except docker.errors.DockerException:
|
||||
_LOGGER.warning("Can't find a HassOS cli %s", self.image)
|
||||
_LOGGER.warning("Can't find a HassOS CLI %s", self.image)
|
||||
|
||||
else:
|
||||
self._meta = image.attrs
|
||||
_LOGGER.info("Found HassOS cli %s with version %s",
|
||||
_LOGGER.info("Found HassOS CLI %s with version %s",
|
||||
self.image, self.version)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""Init file for HassIO docker object."""
|
||||
"""Init file for Hass.io Docker object."""
|
||||
import logging
|
||||
|
||||
import docker
|
||||
|
@ -12,35 +12,35 @@ HASS_DOCKER_NAME = 'homeassistant'
|
|||
|
||||
|
||||
class DockerHomeAssistant(DockerInterface):
|
||||
"""Docker hassio wrapper for HomeAssistant."""
|
||||
"""Docker Hass.io wrapper for Home Assistant."""
|
||||
|
||||
@property
|
||||
def machine(self):
|
||||
"""Return machine of Home-Assistant docker image."""
|
||||
"""Return machine of Home Assistant Docker image."""
|
||||
if self._meta and LABEL_MACHINE in self._meta['Config']['Labels']:
|
||||
return self._meta['Config']['Labels'][LABEL_MACHINE]
|
||||
return None
|
||||
|
||||
@property
|
||||
def image(self):
|
||||
"""Return name of docker image."""
|
||||
"""Return name of Docker image."""
|
||||
return self.sys_homeassistant.image
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return name of docker container."""
|
||||
"""Return name of Docker container."""
|
||||
return HASS_DOCKER_NAME
|
||||
|
||||
@property
|
||||
def devices(self):
|
||||
"""Create list of special device to map into docker."""
|
||||
"""Create list of special device to map into Docker."""
|
||||
devices = []
|
||||
for device in self.sys_hardware.serial_devices:
|
||||
devices.append(f"{device}:{device}:rwm")
|
||||
return devices or None
|
||||
|
||||
def _run(self):
|
||||
"""Run docker image.
|
||||
"""Run Docker image.
|
||||
|
||||
Need run inside executor.
|
||||
"""
|
||||
|
@ -108,7 +108,7 @@ class DockerHomeAssistant(DockerInterface):
|
|||
)
|
||||
|
||||
def is_initialize(self):
|
||||
"""Return True if docker container exists."""
|
||||
"""Return True if Docker container exists."""
|
||||
return self.sys_run_in_executor(self._is_initialize)
|
||||
|
||||
def _is_initialize(self):
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""Interface class for HassIO docker object."""
|
||||
"""Interface class for Hass.io Docker object."""
|
||||
import asyncio
|
||||
from contextlib import suppress
|
||||
import logging
|
||||
|
@ -14,27 +14,27 @@ _LOGGER = logging.getLogger(__name__)
|
|||
|
||||
|
||||
class DockerInterface(CoreSysAttributes):
|
||||
"""Docker hassio interface."""
|
||||
"""Docker Hass.io interface."""
|
||||
|
||||
def __init__(self, coresys):
|
||||
"""Initialize docker base wrapper."""
|
||||
"""Initialize Docker base wrapper."""
|
||||
self.coresys = coresys
|
||||
self._meta = None
|
||||
self.lock = asyncio.Lock(loop=coresys.loop)
|
||||
|
||||
@property
|
||||
def timeout(self):
|
||||
"""Return timeout for docker actions."""
|
||||
"""Return timeout for Docker actions."""
|
||||
return 30
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return name of docker container."""
|
||||
"""Return name of Docker container."""
|
||||
return None
|
||||
|
||||
@property
|
||||
def meta_config(self):
|
||||
"""Return meta data of config for container/image."""
|
||||
"""Return meta data of configuration for container/image."""
|
||||
if not self._meta:
|
||||
return {}
|
||||
return self._meta.get('Config', {})
|
||||
|
@ -46,17 +46,17 @@ class DockerInterface(CoreSysAttributes):
|
|||
|
||||
@property
|
||||
def image(self):
|
||||
"""Return name of docker image."""
|
||||
"""Return name of Docker image."""
|
||||
return self.meta_config.get('Image')
|
||||
|
||||
@property
|
||||
def version(self):
|
||||
"""Return version of docker image."""
|
||||
"""Return version of Docker image."""
|
||||
return self.meta_labels.get(LABEL_VERSION)
|
||||
|
||||
@property
|
||||
def arch(self):
|
||||
"""Return arch of docker image."""
|
||||
"""Return arch of Docker image."""
|
||||
return self.meta_labels.get(LABEL_ARCH)
|
||||
|
||||
@property
|
||||
|
@ -70,7 +70,7 @@ class DockerInterface(CoreSysAttributes):
|
|||
return self.sys_run_in_executor(self._install, tag)
|
||||
|
||||
def _install(self, tag):
|
||||
"""Pull docker image.
|
||||
"""Pull Docker image.
|
||||
|
||||
Need run inside executor.
|
||||
"""
|
||||
|
@ -88,11 +88,11 @@ class DockerInterface(CoreSysAttributes):
|
|||
return True
|
||||
|
||||
def exists(self):
|
||||
"""Return True if docker image exists in local repo."""
|
||||
"""Return True if Docker image exists in local repository."""
|
||||
return self.sys_run_in_executor(self._exists)
|
||||
|
||||
def _exists(self):
|
||||
"""Return True if docker image exists in local repo.
|
||||
"""Return True if Docker image exists in local repository.
|
||||
|
||||
Need run inside executor.
|
||||
"""
|
||||
|
@ -105,14 +105,14 @@ class DockerInterface(CoreSysAttributes):
|
|||
return True
|
||||
|
||||
def is_running(self):
|
||||
"""Return True if docker is Running.
|
||||
"""Return True if Docker is running.
|
||||
|
||||
Return a Future.
|
||||
"""
|
||||
return self.sys_run_in_executor(self._is_running)
|
||||
|
||||
def _is_running(self):
|
||||
"""Return True if docker is Running.
|
||||
"""Return True if Docker is running.
|
||||
|
||||
Need run inside executor.
|
||||
"""
|
||||
|
@ -134,7 +134,7 @@ class DockerInterface(CoreSysAttributes):
|
|||
|
||||
@process_lock
|
||||
def attach(self):
|
||||
"""Attach to running docker container."""
|
||||
"""Attach to running Docker container."""
|
||||
return self.sys_run_in_executor(self._attach)
|
||||
|
||||
def _attach(self):
|
||||
|
@ -157,11 +157,11 @@ class DockerInterface(CoreSysAttributes):
|
|||
|
||||
@process_lock
|
||||
def run(self):
|
||||
"""Run docker image."""
|
||||
"""Run Docker image."""
|
||||
return self.sys_run_in_executor(self._run)
|
||||
|
||||
def _run(self):
|
||||
"""Run docker image.
|
||||
"""Run Docker image.
|
||||
|
||||
Need run inside executor.
|
||||
"""
|
||||
|
@ -169,7 +169,7 @@ class DockerInterface(CoreSysAttributes):
|
|||
|
||||
@process_lock
|
||||
def stop(self):
|
||||
"""Stop/remove docker container."""
|
||||
"""Stop/remove Docker container."""
|
||||
return self.sys_run_in_executor(self._stop)
|
||||
|
||||
def _stop(self):
|
||||
|
@ -183,19 +183,19 @@ class DockerInterface(CoreSysAttributes):
|
|||
return False
|
||||
|
||||
if container.status == 'running':
|
||||
_LOGGER.info("Stop %s docker application", self.image)
|
||||
_LOGGER.info("Stop %s Docker application", self.image)
|
||||
with suppress(docker.errors.DockerException):
|
||||
container.stop(timeout=self.timeout)
|
||||
|
||||
with suppress(docker.errors.DockerException):
|
||||
_LOGGER.info("Clean %s docker application", self.image)
|
||||
_LOGGER.info("Clean %s Docker application", self.image)
|
||||
container.remove(force=True)
|
||||
|
||||
return True
|
||||
|
||||
@process_lock
|
||||
def remove(self):
|
||||
"""Remove docker images."""
|
||||
"""Remove Docker images."""
|
||||
return self.sys_run_in_executor(self._remove)
|
||||
|
||||
def _remove(self):
|
||||
|
@ -203,11 +203,11 @@ class DockerInterface(CoreSysAttributes):
|
|||
|
||||
Need run inside executor.
|
||||
"""
|
||||
# cleanup container
|
||||
# Cleanup container
|
||||
self._stop()
|
||||
|
||||
_LOGGER.info(
|
||||
"Remove docker %s with latest and %s", self.image, self.version)
|
||||
"Remove Docker %s with latest and %s", self.image, self.version)
|
||||
|
||||
try:
|
||||
with suppress(docker.errors.ImageNotFound):
|
||||
|
@ -227,7 +227,7 @@ class DockerInterface(CoreSysAttributes):
|
|||
|
||||
@process_lock
|
||||
def update(self, tag):
|
||||
"""Update a docker image."""
|
||||
"""Update a Docker image."""
|
||||
return self.sys_run_in_executor(self._update, tag)
|
||||
|
||||
def _update(self, tag):
|
||||
|
@ -236,27 +236,27 @@ class DockerInterface(CoreSysAttributes):
|
|||
Need run inside executor.
|
||||
"""
|
||||
_LOGGER.info(
|
||||
"Update docker %s with %s:%s", self.version, self.image, tag)
|
||||
"Update Docker %s with %s:%s", self.version, self.image, tag)
|
||||
|
||||
# update docker image
|
||||
# Update docker image
|
||||
if not self._install(tag):
|
||||
return False
|
||||
|
||||
# stop container & cleanup
|
||||
# Stop container & cleanup
|
||||
self._stop()
|
||||
self._cleanup()
|
||||
|
||||
return True
|
||||
|
||||
def logs(self):
|
||||
"""Return docker logs of container.
|
||||
"""Return Docker logs of container.
|
||||
|
||||
Return a Future.
|
||||
"""
|
||||
return self.sys_run_in_executor(self._logs)
|
||||
|
||||
def _logs(self):
|
||||
"""Return docker logs of container.
|
||||
"""Return Docker logs of container.
|
||||
|
||||
Need run inside executor.
|
||||
"""
|
||||
|
@ -268,7 +268,7 @@ class DockerInterface(CoreSysAttributes):
|
|||
try:
|
||||
return container.logs(tail=100, stdout=True, stderr=True)
|
||||
except docker.errors.DockerException as err:
|
||||
_LOGGER.warning("Can't grap logs from %s: %s", self.image, err)
|
||||
_LOGGER.warning("Can't grep logs from %s: %s", self.image, err)
|
||||
|
||||
@process_lock
|
||||
def cleanup(self):
|
||||
|
@ -291,7 +291,7 @@ class DockerInterface(CoreSysAttributes):
|
|||
continue
|
||||
|
||||
with suppress(docker.errors.DockerException):
|
||||
_LOGGER.info("Cleanup docker images: %s", image.tags)
|
||||
_LOGGER.info("Cleanup Docker images: %s", image.tags)
|
||||
self.sys_docker.images.remove(image.id, force=True)
|
||||
|
||||
return True
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""Internal network manager for HassIO."""
|
||||
"""Internal network manager for Hass.io."""
|
||||
import logging
|
||||
|
||||
import docker
|
||||
|
@ -9,13 +9,13 @@ _LOGGER = logging.getLogger(__name__)
|
|||
|
||||
|
||||
class DockerNetwork:
|
||||
"""Internal HassIO Network.
|
||||
"""Internal Hass.io Network.
|
||||
|
||||
This class is not AsyncIO safe!
|
||||
"""
|
||||
|
||||
def __init__(self, dock):
|
||||
"""Initialize internal hassio network."""
|
||||
"""Initialize internal Hass.io network."""
|
||||
self.docker = dock
|
||||
self.network = self._get_network()
|
||||
|
||||
|
@ -44,7 +44,7 @@ class DockerNetwork:
|
|||
try:
|
||||
return self.docker.networks.get(DOCKER_NETWORK)
|
||||
except docker.errors.NotFound:
|
||||
_LOGGER.info("Can't find HassIO network, create new network")
|
||||
_LOGGER.info("Can't find Hass.io network, create new network")
|
||||
|
||||
ipam_pool = docker.types.IPAMPool(
|
||||
subnet=str(DOCKER_NETWORK_MASK),
|
||||
|
@ -61,7 +61,7 @@ class DockerNetwork:
|
|||
})
|
||||
|
||||
def attach_container(self, container, alias=None, ipv4=None):
|
||||
"""Attach container to hassio network.
|
||||
"""Attach container to Hass.io network.
|
||||
|
||||
Need run inside executor.
|
||||
"""
|
||||
|
@ -77,7 +77,7 @@ class DockerNetwork:
|
|||
return True
|
||||
|
||||
def detach_default_bridge(self, container):
|
||||
"""Detach default docker bridge.
|
||||
"""Detach default Docker bridge.
|
||||
|
||||
Need run inside executor.
|
||||
"""
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""Calc & represent docker stats data."""
|
||||
"""Calc and represent docker stats data."""
|
||||
from contextlib import suppress
|
||||
|
||||
|
||||
|
@ -6,7 +6,7 @@ class DockerStats:
|
|||
"""Hold stats data from container inside."""
|
||||
|
||||
def __init__(self, stats):
|
||||
"""Initialize docker stats."""
|
||||
"""Initialize Docker stats."""
|
||||
self._cpu = 0.0
|
||||
self._network_rx = 0
|
||||
self._network_tx = 0
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""Init file for HassIO docker object."""
|
||||
"""Init file for Hass.io Docker object."""
|
||||
import logging
|
||||
import os
|
||||
|
||||
|
@ -11,11 +11,11 @@ _LOGGER = logging.getLogger(__name__)
|
|||
|
||||
|
||||
class DockerSupervisor(DockerInterface, CoreSysAttributes):
|
||||
"""Docker hassio wrapper for Supervisor."""
|
||||
"""Docker Hass.io wrapper for Supervisor."""
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return name of docker container."""
|
||||
"""Return name of Docker container."""
|
||||
return os.environ['SUPERVISOR_NAME']
|
||||
|
||||
def _attach(self):
|
||||
|
@ -29,14 +29,14 @@ class DockerSupervisor(DockerInterface, CoreSysAttributes):
|
|||
return False
|
||||
|
||||
self._meta = container.attrs
|
||||
_LOGGER.info("Attach to supervisor %s with version %s",
|
||||
_LOGGER.info("Attach to Supervisor %s with version %s",
|
||||
self.image, self.version)
|
||||
|
||||
# if already attach
|
||||
# If already attach
|
||||
if container in self.sys_docker.network.containers:
|
||||
return True
|
||||
|
||||
# attach to network
|
||||
# Attach to network
|
||||
return self.sys_docker.network.attach_container(
|
||||
container, alias=['hassio'],
|
||||
ipv4=self.sys_docker.network.supervisor)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""Host function like audio/dbus/systemd."""
|
||||
"""Host function like audio, D-Bus or systemd."""
|
||||
from contextlib import suppress
|
||||
import logging
|
||||
|
||||
|
@ -35,7 +35,7 @@ class HostManager(CoreSysAttributes):
|
|||
|
||||
@property
|
||||
def apparmor(self):
|
||||
"""Return host apparmor handler."""
|
||||
"""Return host AppArmor handler."""
|
||||
return self._apparmor
|
||||
|
||||
@property
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""Host Audio-support."""
|
||||
"""Host Audio support."""
|
||||
import logging
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
@ -19,7 +19,7 @@ class AlsaAudio(CoreSysAttributes):
|
|||
"""Handle Audio ALSA host data."""
|
||||
|
||||
def __init__(self, coresys):
|
||||
"""Initialize Alsa audio system."""
|
||||
"""Initialize ALSA audio system."""
|
||||
self.coresys = coresys
|
||||
self._data = {
|
||||
ATTR_INPUT: {},
|
||||
|
|
|
@ -13,7 +13,7 @@ SYSTEMD_SERVICES = {'hassos-apparmor.service', 'hassio-apparmor.service'}
|
|||
|
||||
|
||||
class AppArmorControl(CoreSysAttributes):
|
||||
"""Handle host apparmor controls."""
|
||||
"""Handle host AppArmor controls."""
|
||||
|
||||
def __init__(self, coresys):
|
||||
"""Initialize host power handling."""
|
||||
|
@ -23,7 +23,7 @@ class AppArmorControl(CoreSysAttributes):
|
|||
|
||||
@property
|
||||
def available(self):
|
||||
"""Return True if AppArmor is availabe on host."""
|
||||
"""Return True if AppArmor is available on host."""
|
||||
return self._service is not None
|
||||
|
||||
def exists(self, profile):
|
||||
|
@ -62,12 +62,12 @@ class AppArmorControl(CoreSysAttributes):
|
|||
if self.available:
|
||||
await self._reload_service()
|
||||
else:
|
||||
_LOGGER.info("AppArmor is not enabled on Host")
|
||||
_LOGGER.info("AppArmor is not enabled on host")
|
||||
|
||||
async def load_profile(self, profile_name, profile_file):
|
||||
"""Load/Update a new/exists profile into AppArmor."""
|
||||
if not validate_profile(profile_name, profile_file):
|
||||
_LOGGER.error("profile is not valid with name %s", profile_name)
|
||||
_LOGGER.error("Profile is not valid with name %s", profile_name)
|
||||
raise HostAppArmorError()
|
||||
|
||||
# Copy to AppArmor folder
|
||||
|
|
|
@ -24,7 +24,7 @@ class SystemControl(CoreSysAttributes):
|
|||
if flag == HOSTNAME and self.sys_dbus.hostname.is_connected:
|
||||
return
|
||||
|
||||
_LOGGER.error("No %s dbus connection available", flag)
|
||||
_LOGGER.error("No %s D-Bus connection available", flag)
|
||||
raise HostNotSupportedError()
|
||||
|
||||
async def reboot(self):
|
||||
|
@ -51,6 +51,6 @@ class SystemControl(CoreSysAttributes):
|
|||
"""Set local a new Hostname."""
|
||||
self._check_dbus(HOSTNAME)
|
||||
|
||||
_LOGGER.info("Set Hostname %s", hostname)
|
||||
_LOGGER.info("Set hostname %s", hostname)
|
||||
await self.sys_dbus.hostname.set_static_hostname(hostname)
|
||||
await self.sys_host.info.update()
|
||||
|
|
|
@ -48,7 +48,7 @@ class InfoCenter(CoreSysAttributes):
|
|||
async def update(self):
|
||||
"""Update properties over dbus."""
|
||||
if not self.sys_dbus.hostname.is_connected:
|
||||
_LOGGER.error("No hostname dbus connection available")
|
||||
_LOGGER.error("No hostname D-Bus connection available")
|
||||
raise HostNotSupportedError()
|
||||
|
||||
_LOGGER.info("Update local host information")
|
||||
|
|
|
@ -95,5 +95,5 @@ class ServiceInfo:
|
|||
|
||||
@staticmethod
|
||||
def read_from(unit):
|
||||
"""Parse data from dbus into this object."""
|
||||
"""Parse data from D-Bus into this object."""
|
||||
return ServiceInfo(unit[0], unit[1], unit[3])
|
||||
|
|
|
@ -24,7 +24,7 @@ RE_TTY = re.compile(r"tty[A-Z]+")
|
|||
|
||||
|
||||
class Hardware:
|
||||
"""Represent an interface to procfs, sysfs and udev."""
|
||||
"""Representation of an interface to procfs, sysfs and udev."""
|
||||
|
||||
def __init__(self):
|
||||
"""Init hardware object."""
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""Schedule for HassIO."""
|
||||
"""Schedule for Hass.io."""
|
||||
import logging
|
||||
from datetime import date, datetime, time, timedelta
|
||||
|
||||
|
@ -11,7 +11,7 @@ TASK = 'task'
|
|||
|
||||
|
||||
class Scheduler:
|
||||
"""Schedule task inside HassIO."""
|
||||
"""Schedule task inside Hass.io."""
|
||||
|
||||
def __init__(self, loop):
|
||||
"""Initialize task schedule."""
|
||||
|
@ -22,18 +22,18 @@ class Scheduler:
|
|||
def register_task(self, coro_callback, interval, repeat=True):
|
||||
"""Schedule a coroutine.
|
||||
|
||||
The coroutien need to be a callback without arguments.
|
||||
The coroutine need to be a callback without arguments.
|
||||
"""
|
||||
task_id = hash(coro_callback)
|
||||
|
||||
# generate data
|
||||
# Generate data
|
||||
opts = {
|
||||
CALL: coro_callback,
|
||||
INTERVAL: interval,
|
||||
REPEAT: repeat,
|
||||
}
|
||||
|
||||
# schedule task
|
||||
# Schedule task
|
||||
self._data[task_id] = opts
|
||||
self._schedule_task(interval, task_id)
|
||||
|
||||
|
@ -60,7 +60,7 @@ class Scheduler:
|
|||
tomorrow = datetime.combine(
|
||||
date.today() + timedelta(days=1), interval)
|
||||
|
||||
# check if we run it today or next day
|
||||
# Check if we run it today or next day
|
||||
if today > datetime.today():
|
||||
calc = today
|
||||
else:
|
||||
|
@ -68,7 +68,7 @@ class Scheduler:
|
|||
|
||||
job = self.loop.call_at(calc.timestamp(), self._run_task, task_id)
|
||||
else:
|
||||
_LOGGER.fatal("Unknow interval %s (type: %s) for scheduler %s",
|
||||
_LOGGER.fatal("Unknown interval %s (type: %s) for scheduler %s",
|
||||
interval, type(interval), task_id)
|
||||
|
||||
# Store job
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
"""Handle internal services discovery."""
|
||||
|
||||
from .discovery import Discovery # noqa
|
||||
from .mqtt import MQTTService
|
||||
from .data import ServicesData
|
||||
|
|
|
@ -14,10 +14,10 @@ class ServicesData(JsonConfig):
|
|||
|
||||
@property
|
||||
def discovery(self):
|
||||
"""Return discovery data for home-assistant."""
|
||||
"""Return discovery data for Home Assistant."""
|
||||
return self._data[ATTR_DISCOVERY]
|
||||
|
||||
@property
|
||||
def mqtt(self):
|
||||
"""Return settings for mqtt service."""
|
||||
"""Return settings for MQTT service."""
|
||||
return self._data[SERVICE_MQTT]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""Handle discover message for Home-Assistant."""
|
||||
"""Handle discover message for Home Assistant."""
|
||||
import logging
|
||||
from uuid import uuid4
|
||||
|
||||
|
@ -12,7 +12,7 @@ EVENT_DISCOVERY_DEL = 'hassio_discovery_del'
|
|||
|
||||
|
||||
class Discovery(CoreSysAttributes):
|
||||
"""Home-Assistant Discovery handler."""
|
||||
"""Home Assistant Discovery handler."""
|
||||
|
||||
def __init__(self, coresys):
|
||||
"""Initialize discovery handler."""
|
||||
|
@ -53,29 +53,29 @@ class Discovery(CoreSysAttributes):
|
|||
return self.message_obj.values()
|
||||
|
||||
def send(self, provider, component, platform=None, config=None):
|
||||
"""Send a discovery message to Home-Assistant."""
|
||||
"""Send a discovery message to Home Assistant."""
|
||||
message = Message(provider, component, platform, config)
|
||||
|
||||
# Already exists?
|
||||
for exists_message in self.message_obj:
|
||||
if exists_message == message:
|
||||
_LOGGER.warning("Found douplicate discovery message from %s",
|
||||
_LOGGER.warning("Found duplicate discovery message from %s",
|
||||
provider)
|
||||
return exists_message
|
||||
|
||||
_LOGGER.info("Send discovery to Home-Assistant %s/%s from %s",
|
||||
_LOGGER.info("Send discovery to Home Assistant %s/%s from %s",
|
||||
component, platform, provider)
|
||||
self.message_obj[message.uuid] = message
|
||||
self.save()
|
||||
|
||||
# send event to Home-Assistant
|
||||
# Send event to Home Assistant
|
||||
self.sys_create_task(self.sys_homeassistant.send_event(
|
||||
EVENT_DISCOVERY_ADD, {ATTR_UUID: message.uuid}))
|
||||
|
||||
return message
|
||||
|
||||
def remove(self, message):
|
||||
"""Remove a discovery message from Home-Assistant."""
|
||||
"""Remove a discovery message from Home Assistant."""
|
||||
self.message_obj.pop(message.uuid, None)
|
||||
self.save()
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""Provide MQTT Service."""
|
||||
"""Provide the MQTT Service."""
|
||||
import logging
|
||||
|
||||
from .interface import ServiceInterface
|
||||
|
@ -11,7 +11,7 @@ _LOGGER = logging.getLogger(__name__)
|
|||
|
||||
|
||||
class MQTTService(ServiceInterface):
|
||||
"""Provide mqtt services."""
|
||||
"""Provide MQTT services."""
|
||||
|
||||
@property
|
||||
def slug(self):
|
||||
|
@ -35,7 +35,7 @@ class MQTTService(ServiceInterface):
|
|||
|
||||
@property
|
||||
def hass_config(self):
|
||||
"""Return Home-Assistant mqtt config."""
|
||||
"""Return Home Assistant MQTT config."""
|
||||
if not self.enabled:
|
||||
return None
|
||||
|
||||
|
@ -54,18 +54,18 @@ class MQTTService(ServiceInterface):
|
|||
def set_service_data(self, provider, data):
|
||||
"""Write the data into service object."""
|
||||
if self.enabled:
|
||||
_LOGGER.error("It is already a mqtt in use from %s", self.provider)
|
||||
_LOGGER.error("It is already a MQTT in use from %s", self.provider)
|
||||
return False
|
||||
|
||||
self._data.update(data)
|
||||
self._data[ATTR_PROVIDER] = provider
|
||||
|
||||
if provider == 'homeassistant':
|
||||
_LOGGER.info("Use mqtt settings from Home-Assistant")
|
||||
_LOGGER.info("Use MQTT settings from Home Assistant")
|
||||
self.save()
|
||||
return True
|
||||
|
||||
# discover mqtt to homeassistant
|
||||
# Discover MQTT to Home Assistant
|
||||
message = self.sys_discovery.send(
|
||||
provider, SERVICE_MQTT, None, self.hass_config)
|
||||
|
||||
|
@ -76,7 +76,7 @@ class MQTTService(ServiceInterface):
|
|||
def del_service_data(self, provider):
|
||||
"""Remove the data from service object."""
|
||||
if not self.enabled:
|
||||
_LOGGER.warning("Can't remove not exists services.")
|
||||
_LOGGER.warning("Can't remove not exists services")
|
||||
return False
|
||||
|
||||
discovery_id = self._data.get(ATTR_DISCOVERY_ID)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
"""Validate services schema."""
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from ..const import (
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""Represent a snapshot file."""
|
||||
"""Representation of a snapshot file."""
|
||||
import asyncio
|
||||
from base64 import b64decode, b64encode
|
||||
import json
|
||||
|
@ -29,7 +29,7 @@ _LOGGER = logging.getLogger(__name__)
|
|||
|
||||
|
||||
class Snapshot(CoreSysAttributes):
|
||||
"""A signle hassio snapshot."""
|
||||
"""A single Hass.io snapshot."""
|
||||
|
||||
def __init__(self, coresys, tar_file):
|
||||
"""Initialize a snapshot."""
|
||||
|
@ -72,7 +72,7 @@ class Snapshot(CoreSysAttributes):
|
|||
|
||||
@property
|
||||
def addon_list(self):
|
||||
"""Return a list of addons slugs."""
|
||||
"""Return a list of add-ons slugs."""
|
||||
return [addon_data[ATTR_SLUG] for addon_data in self.addons]
|
||||
|
||||
@property
|
||||
|
@ -92,12 +92,12 @@ class Snapshot(CoreSysAttributes):
|
|||
|
||||
@property
|
||||
def homeassistant_version(self):
|
||||
"""Return snapshot homeassistant version."""
|
||||
"""Return snapshot Home Assistant version."""
|
||||
return self._data[ATTR_HOMEASSISTANT].get(ATTR_VERSION)
|
||||
|
||||
@property
|
||||
def homeassistant(self):
|
||||
"""Return snapshot homeassistant data."""
|
||||
"""Return snapshot Home Assistant data."""
|
||||
return self._data[ATTR_HOMEASSISTANT]
|
||||
|
||||
@property
|
||||
|
@ -119,7 +119,7 @@ class Snapshot(CoreSysAttributes):
|
|||
|
||||
def new(self, slug, name, date, sys_type, password=None):
|
||||
"""Initialize a new snapshot."""
|
||||
# init metadata
|
||||
# Init metadata
|
||||
self._data[ATTR_SLUG] = slug
|
||||
self._data[ATTR_NAME] = name
|
||||
self._data[ATTR_DATE] = date
|
||||
|
@ -306,16 +306,16 @@ class Snapshot(CoreSysAttributes):
|
|||
await asyncio.wait(tasks)
|
||||
|
||||
async def store_folders(self, folder_list=None):
|
||||
"""Backup hassio data into snapshot."""
|
||||
"""Backup Hass.io data into snapshot."""
|
||||
folder_list = set(folder_list or ALL_FOLDERS)
|
||||
|
||||
def _folder_save(name):
|
||||
"""Intenal function to snapshot a folder."""
|
||||
"""Internal function to snapshot a folder."""
|
||||
slug_name = name.replace("/", "_")
|
||||
tar_name = Path(self._tmp.name, f"{slug_name}.tar.gz")
|
||||
origin_dir = Path(self.sys_config.path_hassio, name)
|
||||
|
||||
# Check if exsits
|
||||
# Check if exists
|
||||
if not origin_dir.is_dir():
|
||||
_LOGGER.warning("Can't find snapshot folder %s", name)
|
||||
return
|
||||
|
@ -338,7 +338,7 @@ class Snapshot(CoreSysAttributes):
|
|||
await asyncio.wait(tasks)
|
||||
|
||||
async def restore_folders(self, folder_list=None):
|
||||
"""Backup hassio data into snapshot."""
|
||||
"""Backup Hass.io data into snapshot."""
|
||||
folder_list = set(folder_list or self.folders)
|
||||
|
||||
def _folder_restore(name):
|
||||
|
@ -356,7 +356,7 @@ class Snapshot(CoreSysAttributes):
|
|||
if origin_dir.is_dir():
|
||||
remove_folder(origin_dir)
|
||||
|
||||
# Performe a restore
|
||||
# Perform a restore
|
||||
try:
|
||||
_LOGGER.info("Restore folder %s", name)
|
||||
with SecureTarFile(tar_name, 'r', key=self._key) as tar_file:
|
||||
|
@ -372,7 +372,7 @@ class Snapshot(CoreSysAttributes):
|
|||
await asyncio.wait(tasks)
|
||||
|
||||
def store_homeassistant(self):
|
||||
"""Read all data from homeassistant object."""
|
||||
"""Read all data from Home Assistant object."""
|
||||
self.homeassistant[ATTR_VERSION] = self.sys_homeassistant.version
|
||||
self.homeassistant[ATTR_WATCHDOG] = self.sys_homeassistant.watchdog
|
||||
self.homeassistant[ATTR_BOOT] = self.sys_homeassistant.boot
|
||||
|
@ -393,7 +393,7 @@ class Snapshot(CoreSysAttributes):
|
|||
self._encrypt_data(self.sys_homeassistant.api_password)
|
||||
|
||||
def restore_homeassistant(self):
|
||||
"""Write all data to homeassistant object."""
|
||||
"""Write all data to the Home Assistant object."""
|
||||
self.sys_homeassistant.watchdog = self.homeassistant[ATTR_WATCHDOG]
|
||||
self.sys_homeassistant.boot = self.homeassistant[ATTR_BOOT]
|
||||
self.sys_homeassistant.wait_boot = self.homeassistant[ATTR_WAIT_BOOT]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""Util addons functions."""
|
||||
"""Util add-on functions."""
|
||||
import hashlib
|
||||
import shutil
|
||||
import re
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
"""Validate some things around restore."""
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from ..const import (
|
||||
|
|
Loading…
Reference in New Issue