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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -12,6 +12,7 @@ class ContextType(str, Enum):
SYSTEM = "system"
SUPERVISOR = "supervisor"
PLUGIN = "plugin"
ADDON = "addon"
CORE = "core"
OS = "os"
@ -39,6 +40,7 @@ class IssueType(str, Enum):
MISSING_IMAGE = "missing_image"
UPDATE_FAILED = "update_failed"
UPDATE_ROLLBACK = "update_rollback"
FATAL_ERROR = "fatal_error"
class SuggestionType(str, Enum):
@ -46,4 +48,5 @@ class SuggestionType(str, Enum):
CLEAR_FULL_SNAPSHOT = "clear_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,
ContextType.CORE,
"slug",
[SuggestionType.SYSTEM_REPAIR],
[SuggestionType.EXECUTE_REPAIR],
)
assert IssueType.UPDATE_ROLLBACK == coresys.resolution.issues[-1].type
assert ContextType.CORE == coresys.resolution.issues[-1].context
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