Merge pull request #2029 from home-assistant/dev

Release 241
This commit is contained in:
Pascal Vizeli 2020-09-08 10:41:23 +02:00 committed by GitHub
commit ed45f27f3e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
82 changed files with 267 additions and 96 deletions

View File

@ -43,6 +43,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
# Install Python dependencies from requirements.txt if it exists
COPY requirements.txt requirements_tests.txt ./
RUN pip3 install -r requirements.txt -r requirements_tests.txt \
RUN pip3 install -U setuptools pip \
&& pip3 install -r requirements.txt -r requirements_tests.txt \
&& pip3 install tox \
&& rm -f requirements.txt requirements_tests.txt

@ -1 +1 @@
Subproject commit faee2c3e1b16aa758a802b43d39bcb7032bcf722
Subproject commit 0c7c536f73bc8c73aea8c2c3f89114bdd62b9551

View File

@ -1,6 +1,6 @@
aiohttp==3.6.2
async_timeout==3.0.1
attrs==20.1.0
attrs==20.2.0
cchardet==2.1.6
colorlog==4.2.1
cpe==1.2.1

View File

@ -1,7 +1,7 @@
#!/usr/bin/with-contenv bashio
# ==============================================================================
# Start Service service
# Start Supervisor service
# ==============================================================================
export LD_PRELOAD="/usr/local/lib/libjemalloc.so.2"
exec python3 -m supervisor
exec python3 -m supervisor

View File

@ -0,0 +1,8 @@
#!/usr/bin/execlineb -S1
# ==============================================================================
# Take down the S6 supervision tree when Watchdog fails
# ==============================================================================
if { s6-test ${1} -ne 0 }
if { s6-test ${1} -ne 256 }
s6-svscanctl -t /var/run/s6/services

View File

@ -0,0 +1,34 @@
#!/usr/bin/with-contenv bashio
# ==============================================================================
# Start Watchdog service
# ==============================================================================
declare failed_count=0
declare supervisor_state
bashio::log.info "Start local supervisor watchdog..."
while [[ failed_count -lt 2 ]];
do
sleep 300
supervisor_state="$(cat /run/supervisor)"
if [[ "${supervisor_state}" = "running" ]]; then
# Check API
if bashio::supervisor.ping; then
failed_count=0
else
bashio::log.warning "Maybe found an issue on API healthy"
((failed_count++))
fi
elif [[ "close stopping" = *"${supervisor_state}"* ]]; then
bashio::log.warning "Maybe found an issue on shutdown"
((failed_count++))
else
failed_count=0
fi
done
basio::exit.nok "Watchdog detect issue with Supervisor - take container down!"

View File

@ -47,15 +47,12 @@ if __name__ == "__main__":
loop.run_until_complete(coresys.core.setup())
loop.call_soon_threadsafe(loop.create_task, coresys.core.start())
loop.call_soon_threadsafe(bootstrap.reg_signal, loop)
loop.call_soon_threadsafe(bootstrap.reg_signal, loop, coresys)
try:
_LOGGER.info("Run Supervisor")
loop.run_forever()
finally:
_LOGGER.info("Stopping Supervisor")
loop.run_until_complete(coresys.core.stop())
executor.shutdown(wait=False)
loop.close()
_LOGGER.info("Close Supervisor")

View File

@ -87,6 +87,10 @@ class Addon(AddonModel):
self.instance: DockerAddon = DockerAddon(coresys, self)
self.state: AddonState = AddonState.UNKNOWN
def __repr__(self) -> str:
"""Return internal representation."""
return f"<Addon: {self.slug}>"
@property
def in_progress(self) -> bool:
"""Return True if a task is in progress."""

View File

@ -1,9 +1,9 @@
try {
new Function("import('/api/hassio/app/frontend_latest/entrypoint.e3f59ee9.js')")();
new Function("import('/api/hassio/app/frontend_latest/entrypoint.babc4122.js')")();
} catch (err) {
var el = document.createElement('script');
el.src = '/api/hassio/app/frontend_es5/entrypoint.6086a806.js';
el.src = '/api/hassio/app/frontend_es5/entrypoint.028a6bad.js';
document.body.appendChild(el);
}

View File

@ -1 +0,0 @@
{"version":3,"file":"chunk.2b6daa2d9335da34f364.js","sources":["webpack:///chunk.2b6daa2d9335da34f364.js"],"mappings":"AAAA","sourceRoot":""}

View File

@ -1 +0,0 @@
{"version":3,"file":"chunk.2d61d2e5cad84705d92e.js","sources":["webpack:///chunk.2d61d2e5cad84705d92e.js"],"mappings":";AAAA","sourceRoot":""}

View File

@ -0,0 +1 @@
{"version":3,"file":"chunk.3e7c27cbbb8b44bddd5f.js","sources":["webpack:///chunk.3e7c27cbbb8b44bddd5f.js"],"mappings":";AAAA","sourceRoot":""}

View File

@ -0,0 +1 @@
{"version":3,"file":"chunk.4e329b1d42b5358fbe1a.js","sources":["webpack:///chunk.4e329b1d42b5358fbe1a.js"],"mappings":"AAAA","sourceRoot":""}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
{"version":3,"file":"chunk.a0bbc7b092a109a89b49.js","sources":["webpack:///chunk.a0bbc7b092a109a89b49.js"],"mappings":"AAAA","sourceRoot":""}

View File

@ -0,0 +1 @@
{"version":3,"file":"chunk.c1d54f5585b325a620ff.js","sources":["webpack:///chunk.c1d54f5585b325a620ff.js"],"mappings":"AAAA","sourceRoot":""}

View File

@ -1 +0,0 @@
{"version":3,"file":"chunk.cddd872dbf23dca66986.js","sources":["webpack:///chunk.cddd872dbf23dca66986.js"],"mappings":"AAAA","sourceRoot":""}

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
{"version":3,"file":"chunk.d7c7c8539f98733903e7.js","sources":["webpack:///chunk.d7c7c8539f98733903e7.js"],"mappings":"AAAA","sourceRoot":""}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
{"version":3,"file":"entrypoint.028a6bad.js","sources":["webpack:///entrypoint.028a6bad.js"],"mappings":";AAAA","sourceRoot":""}

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
{"version":3,"file":"entrypoint.6086a806.js","sources":["webpack:///entrypoint.6086a806.js"],"mappings":";AAAA","sourceRoot":""}

View File

@ -1,3 +1,3 @@
{
"entrypoint.js": "/api/hassio/app/frontend_es5/entrypoint.6086a806.js"
"entrypoint.js": "/api/hassio/app/frontend_es5/entrypoint.028a6bad.js"
}

View File

@ -0,0 +1 @@
{"version":3,"file":"chunk.65999be5697048c06838.js","sources":["webpack:///chunk.65999be5697048c06838.js"],"mappings":"AAAA;;AAsIA;AACA;;AAEA;;AAEA;;AAEA;AAhBA;AACA;;AAEA;AAeA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0HA","sourceRoot":""}

View File

@ -0,0 +1 @@
{"version":3,"file":"chunk.6bb7ce5727199e27cab7.js","sources":["webpack:///chunk.6bb7ce5727199e27cab7.js"],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAy7EA","sourceRoot":""}

View File

@ -1 +0,0 @@
{"version":3,"file":"chunk.7cb0e1ca56f17d2a6349.js","sources":["webpack:///chunk.7cb0e1ca56f17d2a6349.js"],"mappings":"AAAA;;;AAiHA;AACA;;AAEA;;AATA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+DA","sourceRoot":""}

View File

@ -0,0 +1 @@
{"version":3,"file":"chunk.857ff7ed2c02915f8deb.js","sources":["webpack:///chunk.857ff7ed2c02915f8deb.js"],"mappings":"AAAA;;;AAiHA;AACA;;AAEA;;AATA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+DA","sourceRoot":""}

View File

@ -1 +1 @@
{"version":3,"file":"chunk.bf7e6600f8be3c723cd9.js","sources":["webpack:///chunk.bf7e6600f8be3c723cd9.js"],"mappings":"AAAA;;;AAoMA;AACA;;;AAGA;;;;;AAKA;;AAEA;AAEA;AACA;;;;;;;AAQA;;;;;AAKA;;AAEA;AAEA;AACA;;;;;;;AAQA;;;;;AAOA;;;;;;;;;;;;;;;;AAuBA;AAinBA;;AAEA;;AAEA;AACA;;AAIA;AA0IA;;;;AAIA;;AAEA;AACA;;;AAGA;;;;AAIA;AACA;;;;;;AAQA;;;;;;;;;;;;;;;;;;;;;;AA6HA;;;AAyGA;AACA;;;;;;;;AAQA;;AAGA;;;AAGA;;AAEA;AACA;;;;AAIA;;;;;;;AAQA;;;AAGA;;;;;AAvCA;;;;;;;;;;;;;;;AA8KA;;;AAkFA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AApBA;;;;;;;;;;;AA4CA;;;AA8GA;;AAEA;;;;AARA;;;;;;;;;;;;AAiCA;;AAiCA;AACA;AACA;;;AAMA;;;;AA6IA;;;AAMA;AACA;;;AAGA;;AAEA;;AAKA;;AAEA;;AAEA;;AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6EA;AAsLA;;;;AAIA;AACA;AACA;AACA;;;AAGA;;;;;;;;AAQA;AACA;AACA;;;;AAIA;AACA;;;AAGA;;;AAGA;AACA;;;;;;;AAOA;;;;;;;;;AASA;;AAEA;AACA;;;;AAIA;;AAEA;;;;AAIA;;;AAGA;;;;AAIA;AACA;AACA;;;AAGA;;;;;;AAMA;;AAEA;AACA;;;;AAIA;;;AAGA;;AAEA;;AAEA;AACA;AAIA;;;;;;AAMA;;AAEA;AACA;;AAEA;AAKA;;AAEA;;;;AAIA;;AAEA;;;;;AAKA;;AAEA;AACA;;AAEA;;;;;AAKA;;AAEA;AACA;;AAEA;;;;;AAKA;;AAEA;AACA;;AAEA;;;AAGA;;AAEA;;AAEA;AACA;;AAEA;;;;;AAKA;;AAEA;AACA;;AAEA;;;;;AAKA;;AAEA;AACA;;AAEA;AACA;;;;;AAKA;;AAEA;AACA;;AAEA;;;;;AAKA;;AAEA;AACA;;AAEA;;;;;;AAMA;;;AAGA;;;AAGA;;AAEA;;;;;;;;AAQA;AACA;;;;;AAKA;AACA;;;;;;;;AAQA;AACA;;;;AAIA;AACA;AACA;;;;;;;;;AASA;AACA;;;;AAIA;AACA;AACA;;;;;AAKA;;;AAGA;AACA;AACA;;;;AAIA;AACA;AACA;;;;;;;;AAQA;AACA;;;;AAIA;;AAEA;AACA;;;AAGA;AACA;;;AAGA;AACA;;;;;;AAMA;AACA;;;;AAIA;AACA;;;;AAIA;;AAEA;;;;;;;;;;AAUA;AACA;AACA;;;AAGA;;;AAGA;;;;AAIA;;;AAGA;AACA;;;;AAIA;AACA;AACA;;;;;;AAMA;AACA;;;;;;;;AAQA;;;;AAIA;;;;AAIA;AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAocA;;;AAoFA;AACA;AACA;;;AARA;;;;;;AA4BA;AAqGA;;AAEA;;AAEA;AACA;AACA;;;AAGA;;;AAKA;;;;;;;;;AAgBA;;;AAiGA;AACA;;;AAPA;;;;;;AA2BA;;AAmQA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;;;AAKA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCA","sourceRoot":""}
{"version":3,"file":"chunk.9a51b75455a6b146cba2.js","sources":["webpack:///chunk.9a51b75455a6b146cba2.js"],"mappings":"AAAA;;;AAoMA;AACA;;;AAGA;;;;;AAKA;;AAEA;AAEA;AACA;;;;;;;AAQA;;;;;AAKA;;AAEA;AAEA;AACA;;;;;;;AAQA;;;;;AAOA;;;;;;;;;;;;;;;;AAuBA;AAinBA;;AAEA;;AAEA;AACA;;AAIA;AA0IA;;;;AAIA;;AAEA;AACA;;;AAGA;;;;AAIA;AACA;;;;;;AAQA;;;;;;;;;;;;;;;;;;;;;;AA6HA;;;AAyGA;AACA;;;;;;;;AAQA;;AAGA;;;AAGA;;AAEA;AACA;;;;AAIA;;;;;;;AAQA;;;AAGA;;;;;AAvCA;;;;;;;;;;;;;;;AA8KA;;;AAkFA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AApBA;;;;;;;;;;;AA4CA;;;AA8GA;;AAEA;;;;AARA;;;;;;;;;;;;AAiCA;;AAiCA;AACA;AACA;;;AAMA;;;;AA6IA;;;AAMA;AACA;;;AAGA;;AAEA;;AAKA;;AAEA;;AAEA;;AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6EA;AAsLA;;;;AAIA;AACA;AACA;AACA;;;AAGA;;;;;;;;AAQA;AACA;AACA;;;;AAIA;AACA;;;AAGA;;;AAGA;AACA;;;;;;;AAOA;;;;;;;;;AASA;;AAEA;AACA;;;;AAIA;;AAEA;;;;AAIA;;;AAGA;;;;AAIA;AACA;AACA;;;AAGA;;;;;;AAMA;;AAEA;AACA;;;;AAIA;;;AAGA;;AAEA;;AAEA;AACA;AAIA;;;;;;AAMA;;AAEA;AACA;;AAEA;AAKA;;AAEA;;;;AAIA;;AAEA;;;;;AAKA;;AAEA;AACA;;AAEA;;;;;AAKA;;AAEA;AACA;;AAEA;;;;;AAKA;;AAEA;AACA;;AAEA;;;AAGA;;AAEA;;AAEA;AACA;;AAEA;;;;;AAKA;;AAEA;AACA;;AAEA;;;;;AAKA;;AAEA;AACA;;AAEA;AACA;;;;;AAKA;;AAEA;AACA;;AAEA;;;;;AAKA;;AAEA;AACA;;AAEA;;;;;;AAMA;;;AAGA;;;AAGA;;AAEA;;;;;;;;AAQA;AACA;;;;;AAKA;AACA;;;;;;;;AAQA;AACA;;;;AAIA;AACA;AACA;;;;;;;;;AASA;AACA;;;;AAIA;AACA;AACA;;;;;AAKA;;;AAGA;AACA;AACA;;;;AAIA;AACA;AACA;;;;;;;;AAQA;AACA;;;;AAIA;;AAEA;AACA;;;AAGA;AACA;;;AAGA;AACA;;;;;;AAMA;AACA;;;;AAIA;AACA;;;;AAIA;;AAEA;;;;;;;;;;AAUA;AACA;AACA;;;AAGA;;;AAGA;;;;AAIA;;;AAGA;AACA;;;;AAIA;AACA;AACA;;;;;;AAMA;AACA;;;;;;;;AAQA;;;;AAIA;;;;AAIA;AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAocA;;;AAoFA;AACA;AACA;;;AARA;;;;;;AA4BA;AAqGA;;AAEA;;AAEA;AACA;AACA;;;AAGA;;;AAKA;;;;;;;;;AAgBA;;;AAiGA;AACA;;;AAPA;;;;;;AA2BA;;AAmQA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;;;AAKA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCA","sourceRoot":""}

View File

@ -1 +0,0 @@
{"version":3,"file":"chunk.ca3bb0345abd1f0a8178.js","sources":["webpack:///chunk.ca3bb0345abd1f0a8178.js"],"mappings":"AAAA;;AAsIA;AACA;;AAEA;;AAEA;;AAEA;AAhBA;AACA;;AAEA;AAeA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0HA","sourceRoot":""}

View File

@ -1 +0,0 @@
{"version":3,"file":"chunk.d854c37ea42bebe8601c.js","sources":["webpack:///chunk.d854c37ea42bebe8601c.js"],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAy7EA","sourceRoot":""}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,3 @@
{
"entrypoint.js": "/api/hassio/app/frontend_latest/entrypoint.e3f59ee9.js"
"entrypoint.js": "/api/hassio/app/frontend_latest/entrypoint.babc4122.js"
}

View File

@ -240,20 +240,26 @@ def check_environment() -> None:
_LOGGER.critical("Can't find gdbus!")
def reg_signal(loop) -> None:
def reg_signal(loop, coresys: CoreSys) -> None:
"""Register SIGTERM and SIGKILL to stop system."""
try:
loop.add_signal_handler(signal.SIGTERM, lambda: loop.call_soon(loop.stop))
loop.add_signal_handler(
signal.SIGTERM, lambda: loop.create_task(coresys.core.stop())
)
except (ValueError, RuntimeError):
_LOGGER.warning("Could not bind to SIGTERM")
try:
loop.add_signal_handler(signal.SIGHUP, lambda: loop.call_soon(loop.stop))
loop.add_signal_handler(
signal.SIGHUP, lambda: loop.create_task(coresys.core.stop())
)
except (ValueError, RuntimeError):
_LOGGER.warning("Could not bind to SIGHUP")
try:
loop.add_signal_handler(signal.SIGINT, lambda: loop.call_soon(loop.stop))
loop.add_signal_handler(
signal.SIGINT, lambda: loop.create_task(coresys.core.stop())
)
except (ValueError, RuntimeError):
_LOGGER.warning("Could not bind to SIGINT")

View File

@ -3,7 +3,7 @@ from enum import Enum
from ipaddress import ip_network
from pathlib import Path
SUPERVISOR_VERSION = "240"
SUPERVISOR_VERSION = "241"
URL_HASSIO_ADDONS = "https://github.com/home-assistant/hassio-addons"
URL_HASSIO_APPARMOR = "https://version.home-assistant.io/apparmor.txt"
@ -32,6 +32,7 @@ FILE_HASSIO_UPDATER = Path(SUPERVISOR_DATA, "updater.json")
MACHINE_ID = Path("/etc/machine-id")
SOCKET_DBUS = Path("/run/dbus/system_bus_socket")
SOCKET_DOCKER = Path("/run/docker.sock")
RUN_SUPERVISOR_STATE = Path("/run/supervisor")
DOCKER_NETWORK = "hassio"
DOCKER_NETWORK_MASK = ip_network("172.30.32.0/23")
@ -395,7 +396,9 @@ class CoreState(str, Enum):
STARTUP = "startup"
RUNNING = "running"
FREEZE = "freeze"
SHUTDOWN = "shutdown"
STOPPING = "stopping"
CLOSE = "close"
class LogLevel(str, Enum):

View File

@ -2,10 +2,17 @@
import asyncio
from contextlib import suppress
import logging
from typing import Optional
import async_timeout
from .const import SOCKET_DBUS, SUPERVISED_SUPPORTED_OS, AddonStartup, CoreState
from .const import (
RUN_SUPERVISOR_STATE,
SOCKET_DBUS,
SUPERVISED_SUPPORTED_OS,
AddonStartup,
CoreState,
)
from .coresys import CoreSys, CoreSysAttributes
from .exceptions import (
DockerAPIError,
@ -23,12 +30,31 @@ class Core(CoreSysAttributes):
def __init__(self, coresys: CoreSys):
"""Initialize Supervisor object."""
self.coresys: CoreSys = coresys
self.state: CoreState = CoreState.INITIALIZE
self.healthy: bool = True
self.supported: bool = True
self._state: Optional[CoreState] = None
@property
def state(self) -> CoreState:
"""Return state of the core."""
return self._state
@state.setter
def state(self, new_state: CoreState) -> None:
"""Set core into new state."""
try:
RUN_SUPERVISOR_STATE.write_text(new_state.value)
except OSError as err:
_LOGGER.warning("Can't update supervisor state %s: %s", new_state, err)
finally:
self._state = new_state
async def connect(self):
"""Connect Supervisor container."""
self.state = CoreState.INITIALIZE
# Load information from container
await self.sys_supervisor.load()
# If host docker is supported?
@ -241,8 +267,10 @@ class Core(CoreSysAttributes):
async def stop(self):
"""Stop a running orchestration."""
# store new last boot / prevent time adjustments
if self.state == CoreState.RUNNING:
if self.state in (CoreState.RUNNING, CoreState.SHUTDOWN):
self._update_last_boot()
if self.state in (CoreState.STOPPING, CoreState.CLOSE):
return
# don't process scheduler anymore
self.state = CoreState.STOPPING
@ -269,12 +297,14 @@ class Core(CoreSysAttributes):
_LOGGER.warning("Stage 2: Force Shutdown!")
_LOGGER.info("Supervisor is down")
self.state = CoreState.CLOSE
self.sys_loop.stop()
async def shutdown(self):
"""Shutdown all running containers in correct order."""
# don't process scheduler anymore
if self.state == CoreState.RUNNING:
self.state = CoreState.STOPPING
self.state = CoreState.SHUTDOWN
# Shutdown Application Add-ons, using Home Assistant API
await self.sys_addons.shutdown(AddonStartup.APPLICATION)
@ -289,7 +319,7 @@ class Core(CoreSysAttributes):
await self.sys_addons.shutdown(AddonStartup.INITIALIZE)
# Shutdown all Plugins
if self.state == CoreState.STOPPING:
if self.state in (CoreState.STOPPING, CoreState.SHUTDOWN):
await self.sys_plugins.shutdown()
def _update_last_boot(self):

View File

@ -68,3 +68,4 @@ class WirelessProperties:
properties: dict = attr.ib()
security: dict = attr.ib()
ssid: str = attr.ib()

View File

@ -1,7 +1,7 @@
"""Connection object for Network Manager."""
from typing import Optional
from ...const import ATTR_ADDRESS, ATTR_IPV4, ATTR_METHOD, ATTR_PREFIX
from ...const import ATTR_ADDRESS, ATTR_IPV4, ATTR_METHOD, ATTR_PREFIX, ATTR_SSID
from ...utils.gdbus import DBus
from ..const import (
DBUS_ATTR_802_WIRELESS,
@ -134,6 +134,7 @@ class NetworkConnection(NetworkAttributes):
self._wireless = WirelessProperties(
data.get(DBUS_ATTR_802_WIRELESS, {}),
data.get(DBUS_ATTR_802_WIRELESS_SECURITY, {}),
bytes(data.get(DBUS_ATTR_802_WIRELESS, {}).get(ATTR_SSID, [])).decode(),
)
self._device = NetworkDevice(

View File

@ -35,10 +35,7 @@ def interface_update_payload(interface, **kwargs) -> str:
kwargs[ATTR_SSID] = ", ".join(
[
f"0x{x}"
for x in interface.connection.wireless.properties[ATTR_SSID]
.encode()
.hex(",")
.split(",")
for x in interface.connection.wireless.ssid.encode().hex(",").split(",")
]
)

View File

@ -61,7 +61,10 @@ class Scheduler(CoreSysAttributes):
if self.sys_core.state == CoreState.RUNNING:
await task.coro_callback()
finally:
if task.repeat and self.sys_core.state != CoreState.STOPPING:
if task.repeat and self.sys_core.state not in (
CoreState.STOPPING,
CoreState.CLOSE,
):
self._schedule_task(task)
else:
self._tasks.remove(task)

View File

@ -9,6 +9,10 @@ _LOGGER: logging.Logger = logging.getLogger(__name__)
class AddonStore(AddonModel):
"""Hold data for add-on inside Supervisor."""
def __repr__(self) -> str:
"""Return internal representation."""
return f"<Store: {self.slug}>"
@property
def data(self) -> Data:
"""Return add-on data/config."""

View File

@ -75,7 +75,12 @@ class StoreData(CoreSysAttributes):
def _read_addons_folder(self, path, repository):
"""Read data from add-ons folder."""
try:
addon_list = path.glob("**/config.json")
# Generate a list without artefact, safe for corruptions
addon_list = [
addon
for addon in path.glob("**/config.json")
if ".git" not in addon.parts
]
except OSError as err:
self.sys_core.healthy = False
_LOGGER.critical(
@ -85,10 +90,6 @@ class StoreData(CoreSysAttributes):
return
for addon in addon_list:
# Ingore git artefacts
if ".git" in addon.parts:
continue
try:
addon_config = read_json_file(addon)
except JsonFileError:

View File

@ -124,7 +124,7 @@ class Supervisor(CoreSysAttributes):
with suppress(SupervisorError):
await self.update_apparmor()
self.sys_loop.call_later(5, self.sys_loop.stop)
self.sys_create_task(self.sys_core.stop())
@property
def in_progress(self) -> bool:

View File

@ -10,6 +10,8 @@ from signal import SIGINT
from typing import Any, Dict, List, Optional, Set
import xml.etree.ElementTree as ET
import sentry_sdk
from ..exceptions import (
DBusFatalError,
DBusInterfaceError,
@ -31,7 +33,7 @@ RE_GVARIANT_STRING_ESC: re.Pattern[Any] = re.compile(
RE_GVARIANT_STRING: re.Pattern[Any] = re.compile(
r"(?<=(?: |{|\[|\(|<))'(.*?)'(?=(?:|]|}|,|\)|>))"
)
RE_GVARIANT_BINARY: re.Pattern[Any] = re.compile(r"<\[byte (.*?)\]>")
RE_GVARIANT_BINARY: re.Pattern[Any] = re.compile(r"\[byte (.*?)\]")
RE_GVARIANT_TUPLE_O: re.Pattern[Any] = re.compile(r"\"[^\"\\]*(?:\\.[^\"\\]*)*\"|(\()")
RE_GVARIANT_TUPLE_C: re.Pattern[Any] = re.compile(
r"\"[^\"\\]*(?:\\.[^\"\\]*)*\"|(,?\))"
@ -61,12 +63,7 @@ DBUS_METHOD_GETALL: str = "org.freedesktop.DBus.Properties.GetAll"
def _convert_bytes(value: str) -> str:
"""Convert bytes to string or byte-array."""
data: bytes = bytes(int(char, 0) for char in value.split(", "))
try:
text = data.decode()
except UnicodeDecodeError:
return f"<[{', '.join(str(char) for char in data)}]>"
return f"<'{text}'>"
return f"[{', '.join(str(char) for char in data)}]"
class DBus:
@ -153,7 +150,8 @@ class DBus:
try:
return json.loads(json_raw)
except json.JSONDecodeError as err:
_LOGGER.critical("Can't parse '%s': '%s' - %s", json_raw, raw, err)
_LOGGER.error("Can't parse '%s': '%s' - %s", json_raw, raw, err)
sentry_sdk.capture_exception(err)
raise DBusParseError() from err
@staticmethod

View File

@ -90,11 +90,15 @@ async def coresys(loop, docker, dbus, network_manager, aiohttp_client) -> CoreSy
):
coresys_obj = await initialize_coresys()
# Mock save json
coresys_obj.ingress.save_data = MagicMock()
coresys_obj.arch._default_arch = "amd64"
# Mock test client
coresys_obj.arch._default_arch = "amd64"
coresys_obj._machine = "qemux86-64"
coresys_obj._machine_id = uuid4()
# Mock host communication
coresys_obj._dbus = dbus
coresys_obj._dbus.network = network_manager

View File

@ -32,4 +32,4 @@ async def test_interface_update_payload_wireless(network_interface):
)
assert DBus.parse_gvariant(data)["ipv4"]["method"] == "manual"
assert DBus.parse_gvariant(data)["ipv4"]["address-data"][0]["address"] == "1.1.1.1"
assert DBus.parse_gvariant(data)["802-11-wireless"]["ssid"] == "NETT"
assert DBus.parse_gvariant(data)["802-11-wireless"]["ssid"] == [78, 69, 84, 84]

33
tests/test_core_state.py Normal file
View File

@ -0,0 +1,33 @@
"""Testing handling with CoreState."""
from pathlib import Path
from tempfile import TemporaryDirectory
from unittest.mock import patch
import pytest
from supervisor.const import CoreState
# pylint: disable=redefined-outer-name
@pytest.fixture
def run_dir():
"""Fixture to inject hassio env."""
with patch(
"supervisor.core.RUN_SUPERVISOR_STATE"
) as mock_run, TemporaryDirectory() as tmp_run:
tmp_state = Path(tmp_run, "supervisor")
mock_run.write_text = tmp_state.write_text
yield tmp_state
def test_write_state(run_dir, coresys):
"""Test write corestate to /run/supervisor."""
coresys.core.state = CoreState.RUNNING
assert run_dir.read_text() == CoreState.RUNNING.value
coresys.core.state = CoreState.SHUTDOWN
assert run_dir.read_text() == CoreState.SHUTDOWN.value

View File

@ -325,7 +325,7 @@ def test_networkmanager_binary_data():
"mode": "infrastructure",
"security": "802-11-wireless-security",
"seen-bssids": ["7C:2E:BD:98:1B:06"],
"ssid": "NETT",
"ssid": [78, 69, 84, 84],
},
"connection": {
"id": "NETT",
@ -370,7 +370,7 @@ def test_networkmanager_binary_data():
"mode": "infrastructure",
"security": "802-11-wireless-security",
"seen-bssids": ["7C:2E:BD:98:1B:06"],
"ssid": "NETT",
"ssid": [78, 69, 84, 84],
},
"802-11-wireless-security": {"auth-alg": "open", "key-mgmt": "wpa-psk"},
"connection": {
@ -402,3 +402,23 @@ def test_networkmanager_binary_data():
"proxy": {},
}
]
def test_v6():
"""Test IPv6 Property."""
raw = "({'addresses': <[([byte 0x20, 0x01, 0x04, 0x70, 0x79, 0x2d, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10], uint32 64, [byte 0x20, 0x01, 0x04, 0x70, 0x79, 0x2d, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01])]>, 'dns': <[[byte 0x20, 0x01, 0x04, 0x70, 0x79, 0x2d, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05]]>})"
data = DBus.parse_gvariant(raw)
assert data == [
{
"addresses": [
[
[32, 1, 4, 112, 121, 45, 0, 1, 0, 18, 0, 0, 0, 0, 0, 16],
64,
[32, 1, 4, 112, 121, 45, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1],
]
],
"dns": [[32, 1, 4, 112, 121, 45, 0, 1, 0, 18, 0, 0, 0, 0, 0, 5]],
}
]