Fix new version handling with Plugins (#2159)

This commit is contained in:
Pascal Vizeli 2020-10-22 12:29:53 +02:00 committed by GitHub
parent 0c6c6a6620
commit 01064564b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 48 additions and 37 deletions

View File

@ -2,10 +2,9 @@
import asyncio import asyncio
import logging import logging
from packaging.version import LegacyVersion, parse as pkg_parse
from ..coresys import CoreSys, CoreSysAttributes from ..coresys import CoreSys, CoreSysAttributes
from ..exceptions import HassioError from ..exceptions import HassioError
from ..resolution.const import ContextType, IssueType, SuggestionType
from .audio import Audio from .audio import Audio
from .cli import HaCli from .cli import HaCli
from .dns import CoreDNS from .dns import CoreDNS
@ -18,12 +17,6 @@ _LOGGER: logging.Logger = logging.getLogger(__name__)
class PluginManager(CoreSysAttributes): class PluginManager(CoreSysAttributes):
"""Manage supported function for plugins.""" """Manage supported function for plugins."""
required_cli: LegacyVersion = pkg_parse("2020.10.0")
required_dns: LegacyVersion = pkg_parse("9")
required_audio: LegacyVersion = pkg_parse("17")
required_observer: LegacyVersion = pkg_parse("2020.10.1")
required_multicast: LegacyVersion = pkg_parse("3")
def __init__(self, coresys: CoreSys): def __init__(self, coresys: CoreSys):
"""Initialize plugin manager.""" """Initialize plugin manager."""
self.coresys: CoreSys = coresys self.coresys: CoreSys = coresys
@ -72,44 +65,49 @@ class PluginManager(CoreSysAttributes):
try: try:
await plugin.load() await plugin.load()
except Exception as err: # pylint: disable=broad-except except Exception as err: # pylint: disable=broad-except
_LOGGER.warning("Can't load plugin %s: %s", type(plugin).__name__, err) _LOGGER.warning("Can't load plugin %s: %s", plugin.slug, err)
self.sys_resolution.create_issue(
IssueType.FATAL_ERROR,
ContextType.PLUGIN,
reference=plugin.slug,
suggestions=[SuggestionType.EXECUTE_REPAIR],
)
self.sys_capture_exception(err) self.sys_capture_exception(err)
# Check requirements # Check requirements
for plugin, required_version in ( await self.sys_updater.reload()
(self._audio, self.required_audio), for plugin in (
(self._dns, self.required_dns), self.dns,
(self._cli, self.required_cli), self.audio,
(self._observer, self.required_observer), self.cli,
(self._multicast, self.required_multicast), self.observer,
self.multicast,
): ):
# Check if need an update # Check if need an update
try: if not plugin.need_update:
if pkg_parse(plugin.version) >= required_version: continue
continue
except TypeError:
_LOGGER.warning(
"Unexpected issue while checking requirements for %s",
type(plugin).__name__,
)
_LOGGER.info( _LOGGER.info(
"%s does not have the required version %s, updating", "%s does not have the latest version %s, updating",
type(plugin).__name__, plugin.slug,
required_version, plugin.latest_version,
) )
try: try:
await plugin.update(version=str(required_version)) await plugin.update()
except HassioError: except HassioError:
_LOGGER.error( _LOGGER.error(
"Can't update %s to %s but it's a reuirement, the Supervisor is now in an unhealthy state!", "Can't update %s to %s, the Supervisor healthy could be compromised!",
type(plugin).__name__, plugin.slug,
required_version, plugin.latest_version,
)
self.sys_resolution.create_issue(
IssueType.UPDATE_FAILED,
ContextType.PLUGIN,
reference=plugin.slug,
suggestions=[SuggestionType.EXECUTE_UPDATE],
) )
except Exception as err: # pylint: disable=broad-except except Exception as err: # pylint: disable=broad-except
_LOGGER.warning( _LOGGER.warning("Can't update plugin %s: %s", plugin.slug, err)
"Can't update plugin %s: %s", type(plugin).__name__, err
)
self.sys_capture_exception(err) self.sys_capture_exception(err)
async def repair(self) -> None: async def repair(self) -> None:
@ -136,5 +134,5 @@ class PluginManager(CoreSysAttributes):
try: try:
await plugin.stop() await plugin.stop()
except Exception as err: # pylint: disable=broad-except except Exception as err: # pylint: disable=broad-except
_LOGGER.warning("Can't stop plugin %s: %s", type(plugin).__name__, err) _LOGGER.warning("Can't stop plugin %s: %s", plugin.slug, err)
self.sys_capture_exception(err) self.sys_capture_exception(err)

View File

@ -30,6 +30,8 @@ ASOUND_TMPL: Path = Path(__file__).parents[1].joinpath("data/asound.tmpl")
class Audio(JsonConfig, CoreSysAttributes): class Audio(JsonConfig, CoreSysAttributes):
"""Home Assistant core object for handle audio.""" """Home Assistant core object for handle audio."""
slug: str = "audio"
def __init__(self, coresys: CoreSys): def __init__(self, coresys: CoreSys):
"""Initialize hass object.""" """Initialize hass object."""
super().__init__(FILE_HASSIO_AUDIO, SCHEMA_AUDIO_CONFIG) super().__init__(FILE_HASSIO_AUDIO, SCHEMA_AUDIO_CONFIG)

View File

@ -25,6 +25,8 @@ _LOGGER: logging.Logger = logging.getLogger(__name__)
class HaCli(CoreSysAttributes, JsonConfig): class HaCli(CoreSysAttributes, JsonConfig):
"""HA cli interface inside supervisor.""" """HA cli interface inside supervisor."""
slug: str = "cli"
def __init__(self, coresys: CoreSys): def __init__(self, coresys: CoreSys):
"""Initialize cli handler.""" """Initialize cli handler."""
super().__init__(FILE_HASSIO_CLI, SCHEMA_CLI_CONFIG) super().__init__(FILE_HASSIO_CLI, SCHEMA_CLI_CONFIG)

View File

@ -42,6 +42,8 @@ class HostEntry:
class CoreDNS(JsonConfig, CoreSysAttributes): class CoreDNS(JsonConfig, CoreSysAttributes):
"""Home Assistant core object for handle it.""" """Home Assistant core object for handle it."""
slug: str = "dns"
def __init__(self, coresys: CoreSys): def __init__(self, coresys: CoreSys):
"""Initialize hass object.""" """Initialize hass object."""
super().__init__(FILE_HASSIO_DNS, SCHEMA_DNS_CONFIG) super().__init__(FILE_HASSIO_DNS, SCHEMA_DNS_CONFIG)

View File

@ -24,6 +24,8 @@ _LOGGER: logging.Logger = logging.getLogger(__name__)
class Multicast(JsonConfig, CoreSysAttributes): class Multicast(JsonConfig, CoreSysAttributes):
"""Home Assistant core object for handle it.""" """Home Assistant core object for handle it."""
slug: str = "multicast"
def __init__(self, coresys: CoreSys): def __init__(self, coresys: CoreSys):
"""Initialize hass object.""" """Initialize hass object."""
super().__init__(FILE_HASSIO_MULTICAST, SCHEMA_MULTICAST_CONFIG) super().__init__(FILE_HASSIO_MULTICAST, SCHEMA_MULTICAST_CONFIG)

View File

@ -26,6 +26,8 @@ _LOGGER: logging.Logger = logging.getLogger(__name__)
class Observer(CoreSysAttributes, JsonConfig): class Observer(CoreSysAttributes, JsonConfig):
"""Supervisor observer instance.""" """Supervisor observer instance."""
slug: str = "observer"
def __init__(self, coresys: CoreSys): def __init__(self, coresys: CoreSys):
"""Initialize observer handler.""" """Initialize observer handler."""
super().__init__(FILE_HASSIO_OBSERVER, SCHEMA_OBSERVER_CONFIG) super().__init__(FILE_HASSIO_OBSERVER, SCHEMA_OBSERVER_CONFIG)

View File

@ -12,6 +12,7 @@ class ContextType(str, Enum):
SYSTEM = "system" SYSTEM = "system"
SUPERVISOR = "supervisor" SUPERVISOR = "supervisor"
PLUGIN = "plugin"
ADDON = "addon" ADDON = "addon"
CORE = "core" CORE = "core"
OS = "os" OS = "os"
@ -39,6 +40,7 @@ class IssueType(str, Enum):
MISSING_IMAGE = "missing_image" MISSING_IMAGE = "missing_image"
UPDATE_FAILED = "update_failed" UPDATE_FAILED = "update_failed"
UPDATE_ROLLBACK = "update_rollback" UPDATE_ROLLBACK = "update_rollback"
FATAL_ERROR = "fatal_error"
class SuggestionType(str, Enum): class SuggestionType(str, Enum):
@ -46,4 +48,5 @@ class SuggestionType(str, Enum):
CLEAR_FULL_SNAPSHOT = "clear_full_snapshot" CLEAR_FULL_SNAPSHOT = "clear_full_snapshot"
CREATE_FULL_SNAPSHOT = "create_full_snapshot" CREATE_FULL_SNAPSHOT = "create_full_snapshot"
SYSTEM_REPAIR = "system_repair" EXECUTE_UPDATE = "execute_update"
EXECUTE_REPAIR = "execute_repair"

View File

@ -129,12 +129,12 @@ async def test_resolution_create_issue_suggestion(coresys: CoreSys):
IssueType.UPDATE_ROLLBACK, IssueType.UPDATE_ROLLBACK,
ContextType.CORE, ContextType.CORE,
"slug", "slug",
[SuggestionType.SYSTEM_REPAIR], [SuggestionType.EXECUTE_REPAIR],
) )
assert IssueType.UPDATE_ROLLBACK == coresys.resolution.issues[-1].type assert IssueType.UPDATE_ROLLBACK == coresys.resolution.issues[-1].type
assert ContextType.CORE == coresys.resolution.issues[-1].context assert ContextType.CORE == coresys.resolution.issues[-1].context
assert coresys.resolution.issues[-1].reference == "slug" assert coresys.resolution.issues[-1].reference == "slug"
assert SuggestionType.SYSTEM_REPAIR == coresys.resolution.suggestions[-1].type assert SuggestionType.EXECUTE_REPAIR == coresys.resolution.suggestions[-1].type
assert ContextType.CORE == coresys.resolution.suggestions[-1].context assert ContextType.CORE == coresys.resolution.suggestions[-1].context