mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-09 10:16:29 +00:00
Support plugin requirements & mdns (#1638)
* Support plugin requirements & mdns * better error handling * Use debug from LogLevel * fix lint * fix logger * fix test env * Use new style * fix typo
This commit is contained in:
parent
e787e59b49
commit
e2dc1a4471
@ -96,7 +96,7 @@ function setup_test_env() {
|
|||||||
-e SUPERVISOR_SHARE="/workspaces/test_supervisor" \
|
-e SUPERVISOR_SHARE="/workspaces/test_supervisor" \
|
||||||
-e SUPERVISOR_NAME=hassio_supervisor \
|
-e SUPERVISOR_NAME=hassio_supervisor \
|
||||||
-e SUPERVISOR_DEV=1 \
|
-e SUPERVISOR_DEV=1 \
|
||||||
-e HOMEASSISTANT_REPOSITORY="homeassistant/qemux86-64-homeassistant" \
|
-e SUPERVISOR_MACHINE="qemux86-64" \
|
||||||
homeassistant/amd64-hassio-supervisor:latest
|
homeassistant/amd64-hassio-supervisor:latest
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -38,11 +38,12 @@ from ..const import (
|
|||||||
CONTENT_TYPE_BINARY,
|
CONTENT_TYPE_BINARY,
|
||||||
SUPERVISOR_VERSION,
|
SUPERVISOR_VERSION,
|
||||||
UpdateChannels,
|
UpdateChannels,
|
||||||
|
LogLevel,
|
||||||
)
|
)
|
||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
from ..exceptions import APIError
|
from ..exceptions import APIError
|
||||||
from ..utils.validate import validate_timezone
|
from ..utils.validate import validate_timezone
|
||||||
from ..validate import log_level, repositories, wait_boot
|
from ..validate import repositories, wait_boot
|
||||||
from .utils import api_process, api_process_raw, api_validate
|
from .utils import api_process, api_process_raw, api_validate
|
||||||
|
|
||||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
@ -54,7 +55,7 @@ SCHEMA_OPTIONS = vol.Schema(
|
|||||||
vol.Optional(ATTR_ADDONS_REPOSITORIES): repositories,
|
vol.Optional(ATTR_ADDONS_REPOSITORIES): repositories,
|
||||||
vol.Optional(ATTR_TIMEZONE): validate_timezone,
|
vol.Optional(ATTR_TIMEZONE): validate_timezone,
|
||||||
vol.Optional(ATTR_WAIT_BOOT): wait_boot,
|
vol.Optional(ATTR_WAIT_BOOT): wait_boot,
|
||||||
vol.Optional(ATTR_LOGGING): log_level,
|
vol.Optional(ATTR_LOGGING): vol.Coerce(LogLevel),
|
||||||
vol.Optional(ATTR_DEBUG): vol.Boolean(),
|
vol.Optional(ATTR_DEBUG): vol.Boolean(),
|
||||||
vol.Optional(ATTR_DEBUG_BLOCK): vol.Boolean(),
|
vol.Optional(ATTR_DEBUG_BLOCK): vol.Boolean(),
|
||||||
}
|
}
|
||||||
|
@ -12,12 +12,13 @@ from .api import RestAPI
|
|||||||
from .arch import CpuArch
|
from .arch import CpuArch
|
||||||
from .auth import Auth
|
from .auth import Auth
|
||||||
from .const import (
|
from .const import (
|
||||||
SOCKET_DOCKER,
|
|
||||||
UpdateChannels,
|
|
||||||
ENV_SUPERVISOR_SHARE,
|
|
||||||
ENV_SUPERVISOR_NAME,
|
|
||||||
ENV_HOMEASSISTANT_REPOSITORY,
|
ENV_HOMEASSISTANT_REPOSITORY,
|
||||||
ENV_SUPERVISOR_MACHINE,
|
ENV_SUPERVISOR_MACHINE,
|
||||||
|
ENV_SUPERVISOR_NAME,
|
||||||
|
ENV_SUPERVISOR_SHARE,
|
||||||
|
SOCKET_DOCKER,
|
||||||
|
LogLevel,
|
||||||
|
UpdateChannels,
|
||||||
)
|
)
|
||||||
from .core import Core
|
from .core import Core
|
||||||
from .coresys import CoreSys
|
from .coresys import CoreSys
|
||||||
@ -28,14 +29,14 @@ from .homeassistant import HomeAssistant
|
|||||||
from .host import HostManager
|
from .host import HostManager
|
||||||
from .hwmon import HwMonitor
|
from .hwmon import HwMonitor
|
||||||
from .ingress import Ingress
|
from .ingress import Ingress
|
||||||
|
from .plugins import PluginManager
|
||||||
|
from .secrets import SecretsManager
|
||||||
from .services import ServiceManager
|
from .services import ServiceManager
|
||||||
from .snapshots import SnapshotManager
|
from .snapshots import SnapshotManager
|
||||||
from .store import StoreManager
|
from .store import StoreManager
|
||||||
from .supervisor import Supervisor
|
from .supervisor import Supervisor
|
||||||
from .tasks import Tasks
|
from .tasks import Tasks
|
||||||
from .updater import Updater
|
from .updater import Updater
|
||||||
from .secrets import SecretsManager
|
|
||||||
from .plugins import PluginManager
|
|
||||||
from .utils.dt import fetch_timezone
|
from .utils.dt import fetch_timezone
|
||||||
|
|
||||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
@ -163,7 +164,7 @@ def initialize_system_data(coresys: CoreSys):
|
|||||||
if bool(os.environ.get("SUPERVISOR_DEV", 0)):
|
if bool(os.environ.get("SUPERVISOR_DEV", 0)):
|
||||||
_LOGGER.warning("SUPERVISOR_DEV is set")
|
_LOGGER.warning("SUPERVISOR_DEV is set")
|
||||||
coresys.updater.channel = UpdateChannels.DEV
|
coresys.updater.channel = UpdateChannels.DEV
|
||||||
coresys.config.logging = "debug"
|
coresys.config.logging = LogLevel.DEBUG
|
||||||
coresys.config.debug = True
|
coresys.config.debug = True
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ from .const import (
|
|||||||
ENV_SUPERVISOR_SHARE,
|
ENV_SUPERVISOR_SHARE,
|
||||||
FILE_HASSIO_CONFIG,
|
FILE_HASSIO_CONFIG,
|
||||||
SUPERVISOR_DATA,
|
SUPERVISOR_DATA,
|
||||||
|
LogLevel,
|
||||||
)
|
)
|
||||||
from .utils.dt import parse_datetime
|
from .utils.dt import parse_datetime
|
||||||
from .utils.json import JsonConfig
|
from .utils.json import JsonConfig
|
||||||
@ -89,19 +90,19 @@ class CoreConfig(JsonConfig):
|
|||||||
self._data[ATTR_DEBUG_BLOCK] = value
|
self._data[ATTR_DEBUG_BLOCK] = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def logging(self) -> str:
|
def logging(self) -> LogLevel:
|
||||||
"""Return log level of system."""
|
"""Return log level of system."""
|
||||||
return self._data[ATTR_LOGGING]
|
return self._data[ATTR_LOGGING]
|
||||||
|
|
||||||
@logging.setter
|
@logging.setter
|
||||||
def logging(self, value: str):
|
def logging(self, value: LogLevel):
|
||||||
"""Set system log level."""
|
"""Set system log level."""
|
||||||
self._data[ATTR_LOGGING] = value
|
self._data[ATTR_LOGGING] = value
|
||||||
self.modify_log_level()
|
self.modify_log_level()
|
||||||
|
|
||||||
def modify_log_level(self) -> None:
|
def modify_log_level(self) -> None:
|
||||||
"""Change log level."""
|
"""Change log level."""
|
||||||
lvl = getattr(logging, self.logging.upper())
|
lvl = getattr(logging, str(self.logging.value).upper())
|
||||||
logging.getLogger("supervisor").setLevel(lvl)
|
logging.getLogger("supervisor").setLevel(lvl)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -361,3 +361,13 @@ class CoreStates(str, Enum):
|
|||||||
STARTUP = "startup"
|
STARTUP = "startup"
|
||||||
RUNNING = "running"
|
RUNNING = "running"
|
||||||
FREEZE = "freeze"
|
FREEZE = "freeze"
|
||||||
|
|
||||||
|
|
||||||
|
class LogLevel(str, Enum):
|
||||||
|
"""Logging level of system."""
|
||||||
|
|
||||||
|
DEBUG = "debug"
|
||||||
|
INFO = "info"
|
||||||
|
WARNING = "warning"
|
||||||
|
ERROR = "error"
|
||||||
|
CRITICAL = "critical"
|
||||||
|
@ -2,26 +2,29 @@
|
|||||||
log
|
log
|
||||||
errors
|
errors
|
||||||
loop
|
loop
|
||||||
|
{% if debug %}debug{% endif %}
|
||||||
hosts /config/hosts {
|
hosts /config/hosts {
|
||||||
fallthrough
|
fallthrough
|
||||||
}
|
}
|
||||||
template ANY AAAA local.hass.io hassio {
|
template ANY AAAA local.hass.io hassio {
|
||||||
rcode NOERROR
|
rcode NOERROR
|
||||||
}
|
}
|
||||||
forward . {{ locals | join(" ") }} dns://127.0.0.1:5353 {
|
mdns
|
||||||
|
forward . {{ locals | join(" ") }} dns://127.0.0.1:5553 {
|
||||||
except local.hass.io
|
except local.hass.io
|
||||||
policy sequential
|
policy sequential
|
||||||
health_check 5s
|
health_check 5s
|
||||||
}
|
}
|
||||||
fallback REFUSED . dns://127.0.0.1:5353
|
fallback REFUSED . dns://127.0.0.1:5553
|
||||||
fallback SERVFAIL . dns://127.0.0.1:5353
|
fallback SERVFAIL . dns://127.0.0.1:5553
|
||||||
fallback NXDOMAIN . dns://127.0.0.1:5353
|
fallback NXDOMAIN . dns://127.0.0.1:5553
|
||||||
cache 10
|
cache 10
|
||||||
}
|
}
|
||||||
|
|
||||||
.:5353 {
|
.:5553 {
|
||||||
log
|
log
|
||||||
errors
|
errors
|
||||||
|
{% if debug %}debug{% endif %}
|
||||||
forward . tls://1.1.1.1 tls://1.0.0.1 {
|
forward . tls://1.1.1.1 tls://1.0.0.1 {
|
||||||
tls_servername cloudflare-dns.com
|
tls_servername cloudflare-dns.com
|
||||||
except local.hass.io
|
except local.hass.io
|
||||||
|
@ -3,6 +3,7 @@ import asyncio
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from ..coresys import CoreSys, CoreSysAttributes
|
from ..coresys import CoreSys, CoreSysAttributes
|
||||||
|
from ..exceptions import HassioError
|
||||||
from .audio import Audio
|
from .audio import Audio
|
||||||
from .cli import HaCli
|
from .cli import HaCli
|
||||||
from .dns import CoreDNS
|
from .dns import CoreDNS
|
||||||
@ -14,6 +15,11 @@ _LOGGER: logging.Logger = logging.getLogger(__name__)
|
|||||||
class PluginManager(CoreSysAttributes):
|
class PluginManager(CoreSysAttributes):
|
||||||
"""Manage supported function for plugins."""
|
"""Manage supported function for plugins."""
|
||||||
|
|
||||||
|
required_cli: int = 24
|
||||||
|
required_dns: int = 5
|
||||||
|
required_audio: int = 14
|
||||||
|
required_multicast: int = 2
|
||||||
|
|
||||||
def __init__(self, coresys: CoreSys):
|
def __init__(self, coresys: CoreSys):
|
||||||
"""Initialize plugin manager."""
|
"""Initialize plugin manager."""
|
||||||
self.coresys: CoreSys = coresys
|
self.coresys: CoreSys = coresys
|
||||||
@ -49,6 +55,37 @@ class PluginManager(CoreSysAttributes):
|
|||||||
[self.dns.load(), self.audio.load(), self.cli.load(), self.multicast.load()]
|
[self.dns.load(), self.audio.load(), self.cli.load(), self.multicast.load()]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Check requirements
|
||||||
|
for plugin, required_version in (
|
||||||
|
(self._audio, self.required_audio),
|
||||||
|
(self._dns, self.required_dns),
|
||||||
|
(self._cli, self.required_cli),
|
||||||
|
(self._multicast, self.required_multicast),
|
||||||
|
):
|
||||||
|
# Check if need an update
|
||||||
|
try:
|
||||||
|
if int(plugin.version) >= required_version:
|
||||||
|
continue
|
||||||
|
except TypeError:
|
||||||
|
_LOGGER.warning(
|
||||||
|
"Somethings going wrong with requirements on %s",
|
||||||
|
type(plugin).__name__,
|
||||||
|
)
|
||||||
|
|
||||||
|
_LOGGER.info(
|
||||||
|
"Requirement need update for %s - %i",
|
||||||
|
type(plugin).__name__,
|
||||||
|
required_version,
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
await plugin.update(version=str(required_version))
|
||||||
|
except HassioError:
|
||||||
|
_LOGGER.error(
|
||||||
|
"Can't update %s to %i but it's a reuirement, the Supervisor is not health now!",
|
||||||
|
type(plugin).__name__,
|
||||||
|
required_version,
|
||||||
|
)
|
||||||
|
|
||||||
async def repair(self):
|
async def repair(self):
|
||||||
"""Repair Supervisor plugins."""
|
"""Repair Supervisor plugins."""
|
||||||
await asyncio.wait(
|
await asyncio.wait(
|
||||||
|
@ -13,15 +13,22 @@ import attr
|
|||||||
import jinja2
|
import jinja2
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from ..const import ATTR_IMAGE, ATTR_SERVERS, ATTR_VERSION, DNS_SUFFIX, FILE_HASSIO_DNS
|
from ..const import (
|
||||||
|
ATTR_IMAGE,
|
||||||
|
ATTR_SERVERS,
|
||||||
|
ATTR_VERSION,
|
||||||
|
DNS_SUFFIX,
|
||||||
|
FILE_HASSIO_DNS,
|
||||||
|
LogLevel,
|
||||||
|
)
|
||||||
from ..coresys import CoreSys, CoreSysAttributes
|
from ..coresys import CoreSys, CoreSysAttributes
|
||||||
from ..docker.dns import DockerDNS
|
from ..docker.dns import DockerDNS
|
||||||
from ..docker.stats import DockerStats
|
from ..docker.stats import DockerStats
|
||||||
from ..exceptions import CoreDNSError, CoreDNSUpdateError, DockerAPIError
|
from ..exceptions import CoreDNSError, CoreDNSUpdateError, DockerAPIError
|
||||||
from ..misc.forwarder import DNSForward
|
from ..misc.forwarder import DNSForward
|
||||||
from ..utils.json import JsonConfig
|
from ..utils.json import JsonConfig
|
||||||
from .validate import SCHEMA_DNS_CONFIG
|
|
||||||
from ..validate import dns_url
|
from ..validate import dns_url
|
||||||
|
from .validate import SCHEMA_DNS_CONFIG
|
||||||
|
|
||||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -301,7 +308,9 @@ class CoreDNS(JsonConfig, CoreSysAttributes):
|
|||||||
_LOGGER.warning("Ignore invalid DNS Server: %s", server)
|
_LOGGER.warning("Ignore invalid DNS Server: %s", server)
|
||||||
|
|
||||||
# Generate config file
|
# Generate config file
|
||||||
data = self.coredns_template.render(locals=dns_servers)
|
data = self.coredns_template.render(
|
||||||
|
locals=dns_servers, debug=self.sys_config.logging == LogLevel.DEBUG
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.corefile.write_text(data)
|
self.corefile.write_text(data)
|
||||||
|
@ -34,6 +34,7 @@ from .const import (
|
|||||||
ATTR_VERSION,
|
ATTR_VERSION,
|
||||||
ATTR_WAIT_BOOT,
|
ATTR_WAIT_BOOT,
|
||||||
ATTR_WATCHDOG,
|
ATTR_WATCHDOG,
|
||||||
|
LogLevel,
|
||||||
UpdateChannels,
|
UpdateChannels,
|
||||||
)
|
)
|
||||||
from .utils.validate import validate_timezone
|
from .utils.validate import validate_timezone
|
||||||
@ -48,7 +49,6 @@ docker_image = vol.Match(r"^[\w{}]+/[\-\w{}]+$")
|
|||||||
uuid_match = vol.Match(r"^[0-9a-f]{32}$")
|
uuid_match = vol.Match(r"^[0-9a-f]{32}$")
|
||||||
sha256 = vol.Match(r"^[0-9a-f]{64}$")
|
sha256 = vol.Match(r"^[0-9a-f]{64}$")
|
||||||
token = vol.Match(r"^[0-9a-f]{32,256}$")
|
token = vol.Match(r"^[0-9a-f]{32,256}$")
|
||||||
log_level = vol.In(["debug", "info", "warning", "error", "critical"])
|
|
||||||
|
|
||||||
|
|
||||||
def dns_url(url: str) -> str:
|
def dns_url(url: str) -> str:
|
||||||
@ -156,7 +156,7 @@ SCHEMA_SUPERVISOR_CONFIG = vol.Schema(
|
|||||||
default=["https://github.com/hassio-addons/repository"],
|
default=["https://github.com/hassio-addons/repository"],
|
||||||
): repositories,
|
): repositories,
|
||||||
vol.Optional(ATTR_WAIT_BOOT, default=5): wait_boot,
|
vol.Optional(ATTR_WAIT_BOOT, default=5): wait_boot,
|
||||||
vol.Optional(ATTR_LOGGING, default="info"): log_level,
|
vol.Optional(ATTR_LOGGING, default=LogLevel.INFO): vol.Coerce(LogLevel),
|
||||||
vol.Optional(ATTR_DEBUG, default=False): vol.Boolean(),
|
vol.Optional(ATTR_DEBUG, default=False): vol.Boolean(),
|
||||||
vol.Optional(ATTR_DEBUG_BLOCK, default=False): vol.Boolean(),
|
vol.Optional(ATTR_DEBUG_BLOCK, default=False): vol.Boolean(),
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user