From 8d7b15cbeb0069edc866de1160e94ab3075ba382 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Thu, 13 Aug 2020 16:49:34 +0200 Subject: [PATCH] Improve supported / healthy handling and more checks (#1905) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Joakim Sørensen --- supervisor/api/host.py | 2 +- supervisor/api/info.py | 2 +- supervisor/api/supervisor.py | 2 +- supervisor/const.py | 2 ++ supervisor/core.py | 50 ++++++++++++++++++++++++++---------- supervisor/coresys.py | 8 ------ supervisor/host/__init__.py | 2 +- supervisor/misc/hwmon.py | 2 +- 8 files changed, 43 insertions(+), 27 deletions(-) diff --git a/supervisor/api/host.py b/supervisor/api/host.py index 2e2361164..b5be7fe2f 100644 --- a/supervisor/api/host.py +++ b/supervisor/api/host.py @@ -39,7 +39,7 @@ class APIHost(CoreSysAttributes): return { ATTR_CHASSIS: self.sys_host.info.chassis, ATTR_CPE: self.sys_host.info.cpe, - ATTR_FEATURES: self.sys_host.supperted_features, + ATTR_FEATURES: self.sys_host.supported_features, ATTR_HOSTNAME: self.sys_host.info.hostname, ATTR_OPERATING_SYSTEM: self.sys_host.info.operating_system, ATTR_DEPLOYMENT: self.sys_host.info.deployment, diff --git a/supervisor/api/info.py b/supervisor/api/info.py index 6b25cf800..d3cc898b8 100644 --- a/supervisor/api/info.py +++ b/supervisor/api/info.py @@ -39,7 +39,7 @@ class APIInfo(CoreSysAttributes): ATTR_MACHINE: self.sys_machine, ATTR_ARCH: self.sys_arch.default, ATTR_SUPPORTED_ARCH: self.sys_arch.supported, - ATTR_SUPPORTED: self.sys_supported, + ATTR_SUPPORTED: self.sys_core.supported, ATTR_CHANNEL: self.sys_updater.channel, ATTR_LOGGING: self.sys_config.logging, ATTR_TIMEZONE: self.sys_timezone, diff --git a/supervisor/api/supervisor.py b/supervisor/api/supervisor.py index 2b9a09728..067ef42de 100644 --- a/supervisor/api/supervisor.py +++ b/supervisor/api/supervisor.py @@ -100,7 +100,7 @@ class APISupervisor(CoreSysAttributes): ATTR_VERSION_LATEST: self.sys_updater.version_supervisor, ATTR_CHANNEL: self.sys_updater.channel, ATTR_ARCH: self.sys_supervisor.arch, - ATTR_SUPPORTED: self.sys_supported, + ATTR_SUPPORTED: self.sys_core.supported, ATTR_HEALTHY: self.sys_core.healthy, ATTR_IP_ADDRESS: str(self.sys_supervisor.ip_address), ATTR_WAIT_BOOT: self.sys_config.wait_boot, diff --git a/supervisor/const.py b/supervisor/const.py index 73b101b0d..4d4339ee1 100644 --- a/supervisor/const.py +++ b/supervisor/const.py @@ -329,6 +329,8 @@ ROLE_ALL = [ROLE_DEFAULT, ROLE_HOMEASSISTANT, ROLE_BACKUP, ROLE_MANAGER, ROLE_AD CHAN_ID = "chan_id" CHAN_TYPE = "chan_type" +SUPERVISED_SUPPORTED_OS = ["Debian GNU/Linux 10 (buster)"] + class AddonStartup(str, Enum): """Startup types of Add-on.""" diff --git a/supervisor/core.py b/supervisor/core.py index 85e441f5e..2776c90cd 100644 --- a/supervisor/core.py +++ b/supervisor/core.py @@ -5,7 +5,7 @@ import logging import async_timeout -from .const import SOCKET_DBUS, AddonStartup, CoreStates +from .const import SOCKET_DBUS, SUPERVISED_SUPPORTED_OS, AddonStartup, CoreStates from .coresys import CoreSys, CoreSysAttributes from .exceptions import HassioError, HomeAssistantError, SupervisorUpdateError @@ -19,12 +19,8 @@ class Core(CoreSysAttributes): """Initialize Supervisor object.""" self.coresys: CoreSys = coresys self.state: CoreStates = CoreStates.INITIALIZE - self._healthy: bool = True - - @property - def healthy(self) -> bool: - """Return True if system is healthy.""" - return self._healthy and self.sys_supported + self.healthy: bool = True + self.supported: bool = True async def connect(self): """Connect Supervisor container.""" @@ -32,23 +28,25 @@ class Core(CoreSysAttributes): # If host docker is supported? if not self.sys_docker.info.supported_version: - self.coresys.supported = False + self.supported = False + self.healthy = False _LOGGER.error( "Docker version %s is not supported by Supervisor!", self.sys_docker.info.version, ) elif self.sys_docker.info.inside_lxc: - self.coresys.supported = False + self.supported = False + self.healthy = False _LOGGER.error( "Detected Docker running inside LXC. Running Home Assistant with the Supervisor on LXC is not supported!" ) if self.sys_docker.info.check_requirements(): - self.coresys.supported = False + self.supported = False # Dbus available if not SOCKET_DBUS.exists(): - self.coresys.supported = False + self.supported = False _LOGGER.error( "DBus is required for Home Assistant. This system is not supported!" ) @@ -60,13 +58,13 @@ class Core(CoreSysAttributes): self.sys_config.version == "dev" or self.sys_supervisor.instance.version == "dev" ): - self.coresys.supported = False + self.supported = False _LOGGER.warning( "Found a development supervisor outside dev channel (%s)", self.sys_updater.channel, ) elif self.sys_config.version != self.sys_supervisor.version: - self._healthy = False + self.healthy = False _LOGGER.error( "Update %s of Supervisor %s fails!", self.sys_config.version, @@ -122,13 +120,37 @@ class Core(CoreSysAttributes): # Load secrets await self.sys_secrets.load() + # Check supported OS + if not self.sys_hassos.available: + if self.sys_host.info.operating_system not in SUPERVISED_SUPPORTED_OS: + self.supported = False + _LOGGER.error( + "Using '%s' as the OS is not supported", + self.sys_host.info.operating_system, + ) + else: + # Check rauc connectivity on our OS + if not self.sys_dbus.rauc.is_connected: + self.healthy = False + + # Check all DBUS connectivity + if not self.sys_dbus.hostname.is_connected: + self.supported = False + _LOGGER.error("Hostname DBUS is not connected") + if not self.sys_dbus.nmi_dns.is_connected: + self.supported = False + _LOGGER.error("NetworkManager DNS DBUS is not connected") + if not self.sys_dbus.systemd.is_connected: + self.supported = False + _LOGGER.error("Systemd DBUS is not connected") + async def start(self): """Start Supervisor orchestration.""" self.state = CoreStates.STARTUP await self.sys_api.start() # Check if system is healthy - if not self.sys_supported: + if not self.supported: _LOGGER.critical("System running in a unsupported environment!") elif not self.healthy: _LOGGER.critical( diff --git a/supervisor/coresys.py b/supervisor/coresys.py index ab10c2631..eb8b0bc6b 100644 --- a/supervisor/coresys.py +++ b/supervisor/coresys.py @@ -48,9 +48,6 @@ class CoreSys: self._machine_id: Optional[str] = None self._machine: Optional[str] = None - # Static attributes - self.supported: bool = True - # External objects self._loop: asyncio.BaseEventLoop = asyncio.get_running_loop() self._websession: aiohttp.ClientSession = aiohttp.ClientSession() @@ -462,11 +459,6 @@ class CoreSysAttributes: """Return True if we run dev mode.""" return self.coresys.dev - @property - def sys_supported(self) -> bool: - """Return True if the system is supported.""" - return self.coresys.supported - @property def sys_timezone(self) -> str: """Return timezone.""" diff --git a/supervisor/host/__init__.py b/supervisor/host/__init__.py index c88ec8598..e4bb5b71e 100644 --- a/supervisor/host/__init__.py +++ b/supervisor/host/__init__.py @@ -66,7 +66,7 @@ class HostManager(CoreSysAttributes): return self._sound @property - def supperted_features(self): + def supported_features(self): """Return a list of supported host features.""" features = [] diff --git a/supervisor/misc/hwmon.py b/supervisor/misc/hwmon.py index db6c6dab5..b36375f30 100644 --- a/supervisor/misc/hwmon.py +++ b/supervisor/misc/hwmon.py @@ -28,7 +28,7 @@ class HwMonitor(CoreSysAttributes): self.monitor = pyudev.Monitor.from_netlink(self.context) self.observer = pyudev.MonitorObserver(self.monitor, self._udev_events) except OSError: - self.coresys.supported = False + self.sys_core.healthy = False _LOGGER.critical("Not privileged to run udev monitor!") else: self.observer.start()