Skip to content

Deprecate i386 and armhf Supervisor architectures #5620

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions supervisor/homeassistant/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ async def install(self) -> None:
JobCondition.INTERNET_HOST,
JobCondition.PLUGINS_UPDATED,
JobCondition.SUPERVISOR_UPDATED,
JobCondition.ARCHITECTURE_SUPPORTED,
],
limit=JobExecutionLimit.GROUP_ONCE,
on_condition=HomeAssistantJobError,
Expand Down
1 change: 1 addition & 0 deletions supervisor/jobs/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class JobCondition(StrEnum):
PLUGINS_UPDATED = "plugins_updated"
RUNNING = "running"
SUPERVISOR_UPDATED = "supervisor_updated"
ARCHITECTURE_SUPPORTED = "architecture_supported"


class JobExecutionLimit(StrEnum):
Expand Down
15 changes: 14 additions & 1 deletion supervisor/jobs/decorator.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@
JobGroupExecutionLimitExceeded,
)
from ..host.const import HostFeature
from ..resolution.const import MINIMUM_FREE_SPACE_THRESHOLD, ContextType, IssueType
from ..resolution.const import (
MINIMUM_FREE_SPACE_THRESHOLD,
ContextType,
IssueType,
UnsupportedReason,
)
from ..utils.sentry import capture_exception
from . import SupervisorJob
from .const import JobCondition, JobExecutionLimit
Expand Down Expand Up @@ -435,6 +440,14 @@ async def check_conditions(
raise JobConditionException(
f"'{method_name}' blocked from execution, supervisor needs to be updated first"
)
if (
JobCondition.ARCHITECTURE_SUPPORTED in used_conditions
and UnsupportedReason.SYSTEM_ARCHITECTURE
in coresys.sys_resolution.unsupported
):
raise JobConditionException(
f"'{method_name}' blocked from execution, unsupported system architecture"
)

if JobCondition.PLUGINS_UPDATED in used_conditions and (
out_of_date := [
Expand Down
1 change: 1 addition & 0 deletions supervisor/misc/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ async def _update_addons(self):
JobCondition.HEALTHY,
JobCondition.INTERNET_HOST,
JobCondition.RUNNING,
JobCondition.ARCHITECTURE_SUPPORTED,
],
limit=JobExecutionLimit.ONCE,
)
Expand Down
1 change: 1 addition & 0 deletions supervisor/plugins/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@
JobCondition.HEALTHY,
JobCondition.INTERNET_HOST,
JobCondition.SUPERVISOR_UPDATED,
JobCondition.ARCHITECTURE_SUPPORTED,
]
1 change: 1 addition & 0 deletions supervisor/resolution/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class UnsupportedReason(StrEnum):
SYSTEMD_JOURNAL = "systemd_journal"
SYSTEMD_RESOLVED = "systemd_resolved"
VIRTUALIZATION_IMAGE = "virtualization_image"
SYSTEM_ARCHITECTURE = "system_architecture"


class UnhealthyReason(StrEnum):
Expand Down
37 changes: 37 additions & 0 deletions supervisor/resolution/evaluations/system_architecture.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""Evaluation class for system architecture support."""

from ...const import CoreState
from ...coresys import CoreSys
from ..const import UnsupportedReason
from .base import EvaluateBase


def setup(coresys: CoreSys) -> EvaluateBase:
"""Initialize evaluation-setup function."""
return EvaluateSystemArchitecture(coresys)


class EvaluateSystemArchitecture(EvaluateBase):
"""Evaluate if the current Supervisor architecture is supported."""

@property
def reason(self) -> UnsupportedReason:
"""Return a UnsupportedReason enum."""
return UnsupportedReason.SYSTEM_ARCHITECTURE

@property
def on_failure(self) -> str:
"""Return a string that is printed when self.evaluate is True."""
return "System architecture is no longer supported. Move to a supported system architecture."

@property
def states(self) -> list[CoreState]:
"""Return a list of valid states when this evaluation can run."""
return [CoreState.INITIALIZE]

async def evaluate(self):
"""Run evaluation."""
return self.sys_host.info.sys_arch.supervisor in {
"i386",
"armhf",
}
2 changes: 1 addition & 1 deletion supervisor/updater.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ async def _check_connectivity(self, connectivity: bool):

@Job(
name="updater_fetch_data",
conditions=[JobCondition.INTERNET_SYSTEM],
conditions=[JobCondition.INTERNET_SYSTEM, JobCondition.ARCHITECTURE_SUPPORTED],
on_condition=UpdaterJobError,
limit=JobExecutionLimit.THROTTLE_WAIT,
throttle_period=timedelta(seconds=30),
Expand Down
43 changes: 43 additions & 0 deletions tests/resolution/evaluation/test_system_architecture.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""Test evaluation supported system architectures."""

from unittest.mock import PropertyMock, patch

import pytest

from supervisor.const import CoreState
from supervisor.coresys import CoreSys
from supervisor.resolution.evaluations.system_architecture import (
EvaluateSystemArchitecture,
)


@pytest.mark.parametrize("arch", ["i386", "armhf"])
async def test_evaluation_unsupported_architectures(
coresys: CoreSys,
arch: str,
):
"""Test evaluation of unsupported system architectures."""
system_architecture = EvaluateSystemArchitecture(coresys)
coresys.core.state = CoreState.INITIALIZE

with patch.object(
type(coresys.supervisor), "arch", PropertyMock(return_value=arch)
):
await system_architecture()
assert system_architecture.reason in coresys.resolution.unsupported


@pytest.mark.parametrize("arch", ["amd64", "aarch64", "armv7"])
async def test_evaluation_supported_architectures(
coresys: CoreSys,
arch: str,
):
"""Test evaluation of supported system architectures."""
system_architecture = EvaluateSystemArchitecture(coresys)
coresys.core.state = CoreState.INITIALIZE

with patch.object(
type(coresys.supervisor), "arch", PropertyMock(return_value=arch)
):
await system_architecture()
assert system_architecture.reason not in coresys.resolution.unsupported