mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-29 12:06:30 +00:00
Compare commits
7 Commits
1597497282
...
26ce2a1a90
Author | SHA1 | Date | |
---|---|---|---|
![]() |
26ce2a1a90 | ||
![]() |
ad5827d33f | ||
![]() |
249464e928 | ||
![]() |
3bc55c054a | ||
![]() |
503dc232c4 | ||
![]() |
3ae4744dd0 | ||
![]() |
42069a358e |
@ -28,15 +28,15 @@ RUN \
|
|||||||
\
|
\
|
||||||
&& curl -Lso /usr/bin/cosign "https://github.com/home-assistant/cosign/releases/download/${COSIGN_VERSION}/cosign_${BUILD_ARCH}" \
|
&& curl -Lso /usr/bin/cosign "https://github.com/home-assistant/cosign/releases/download/${COSIGN_VERSION}/cosign_${BUILD_ARCH}" \
|
||||||
&& chmod a+x /usr/bin/cosign \
|
&& chmod a+x /usr/bin/cosign \
|
||||||
&& pip3 install uv==0.2.21
|
&& pip3 install uv==0.6.1
|
||||||
|
|
||||||
# Install requirements
|
# Install requirements
|
||||||
COPY requirements.txt .
|
COPY requirements.txt .
|
||||||
RUN \
|
RUN \
|
||||||
if [ "${BUILD_ARCH}" = "i386" ]; then \
|
if [ "${BUILD_ARCH}" = "i386" ]; then \
|
||||||
linux32 uv pip install --no-build -r requirements.txt; \
|
linux32 uv pip install --compile-bytecode --no-build -r requirements.txt; \
|
||||||
else \
|
else \
|
||||||
uv pip install --no-build -r requirements.txt; \
|
uv pip install --compile-bytecode --no-build -r requirements.txt; \
|
||||||
fi \
|
fi \
|
||||||
&& rm -f requirements.txt
|
&& rm -f requirements.txt
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ pyudev==0.24.3
|
|||||||
PyYAML==6.0.2
|
PyYAML==6.0.2
|
||||||
requests==2.32.3
|
requests==2.32.3
|
||||||
securetar==2025.2.0
|
securetar==2025.2.0
|
||||||
sentry-sdk==2.21.0
|
sentry-sdk==2.22.0
|
||||||
setuptools==75.8.0
|
setuptools==75.8.0
|
||||||
voluptuous==0.15.2
|
voluptuous==0.15.2
|
||||||
dbus-fast==2.33.0
|
dbus-fast==2.33.0
|
||||||
|
@ -221,6 +221,7 @@ class HomeAssistantCore(JobGroup):
|
|||||||
JobCondition.INTERNET_HOST,
|
JobCondition.INTERNET_HOST,
|
||||||
JobCondition.PLUGINS_UPDATED,
|
JobCondition.PLUGINS_UPDATED,
|
||||||
JobCondition.SUPERVISOR_UPDATED,
|
JobCondition.SUPERVISOR_UPDATED,
|
||||||
|
JobCondition.ARCHITECTURE_SUPPORTED,
|
||||||
],
|
],
|
||||||
limit=JobExecutionLimit.GROUP_ONCE,
|
limit=JobExecutionLimit.GROUP_ONCE,
|
||||||
on_condition=HomeAssistantJobError,
|
on_condition=HomeAssistantJobError,
|
||||||
|
@ -32,6 +32,7 @@ class JobCondition(StrEnum):
|
|||||||
PLUGINS_UPDATED = "plugins_updated"
|
PLUGINS_UPDATED = "plugins_updated"
|
||||||
RUNNING = "running"
|
RUNNING = "running"
|
||||||
SUPERVISOR_UPDATED = "supervisor_updated"
|
SUPERVISOR_UPDATED = "supervisor_updated"
|
||||||
|
ARCHITECTURE_SUPPORTED = "architecture_supported"
|
||||||
|
|
||||||
|
|
||||||
class JobExecutionLimit(StrEnum):
|
class JobExecutionLimit(StrEnum):
|
||||||
|
@ -17,7 +17,12 @@ from ..exceptions import (
|
|||||||
JobGroupExecutionLimitExceeded,
|
JobGroupExecutionLimitExceeded,
|
||||||
)
|
)
|
||||||
from ..host.const import HostFeature
|
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 ..utils.sentry import capture_exception
|
||||||
from . import SupervisorJob
|
from . import SupervisorJob
|
||||||
from .const import JobCondition, JobExecutionLimit
|
from .const import JobCondition, JobExecutionLimit
|
||||||
@ -435,6 +440,14 @@ class Job(CoreSysAttributes):
|
|||||||
raise JobConditionException(
|
raise JobConditionException(
|
||||||
f"'{method_name}' blocked from execution, supervisor needs to be updated first"
|
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 (
|
if JobCondition.PLUGINS_UPDATED in used_conditions and (
|
||||||
out_of_date := [
|
out_of_date := [
|
||||||
|
@ -150,6 +150,7 @@ class Tasks(CoreSysAttributes):
|
|||||||
JobCondition.HEALTHY,
|
JobCondition.HEALTHY,
|
||||||
JobCondition.INTERNET_HOST,
|
JobCondition.INTERNET_HOST,
|
||||||
JobCondition.RUNNING,
|
JobCondition.RUNNING,
|
||||||
|
JobCondition.ARCHITECTURE_SUPPORTED,
|
||||||
],
|
],
|
||||||
limit=JobExecutionLimit.ONCE,
|
limit=JobExecutionLimit.ONCE,
|
||||||
)
|
)
|
||||||
|
@ -23,4 +23,5 @@ PLUGIN_UPDATE_CONDITIONS = [
|
|||||||
JobCondition.HEALTHY,
|
JobCondition.HEALTHY,
|
||||||
JobCondition.INTERNET_HOST,
|
JobCondition.INTERNET_HOST,
|
||||||
JobCondition.SUPERVISOR_UPDATED,
|
JobCondition.SUPERVISOR_UPDATED,
|
||||||
|
JobCondition.ARCHITECTURE_SUPPORTED,
|
||||||
]
|
]
|
||||||
|
@ -58,6 +58,7 @@ class UnsupportedReason(StrEnum):
|
|||||||
SYSTEMD_JOURNAL = "systemd_journal"
|
SYSTEMD_JOURNAL = "systemd_journal"
|
||||||
SYSTEMD_RESOLVED = "systemd_resolved"
|
SYSTEMD_RESOLVED = "systemd_resolved"
|
||||||
VIRTUALIZATION_IMAGE = "virtualization_image"
|
VIRTUALIZATION_IMAGE = "virtualization_image"
|
||||||
|
SYSTEM_ARCHITECTURE = "system_architecture"
|
||||||
|
|
||||||
|
|
||||||
class UnhealthyReason(StrEnum):
|
class UnhealthyReason(StrEnum):
|
||||||
|
37
supervisor/resolution/evaluations/system_architecture.py
Normal file
37
supervisor/resolution/evaluations/system_architecture.py
Normal file
@ -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",
|
||||||
|
}
|
@ -196,7 +196,7 @@ class Updater(FileConfiguration, CoreSysAttributes):
|
|||||||
|
|
||||||
@Job(
|
@Job(
|
||||||
name="updater_fetch_data",
|
name="updater_fetch_data",
|
||||||
conditions=[JobCondition.INTERNET_SYSTEM],
|
conditions=[JobCondition.INTERNET_SYSTEM, JobCondition.ARCHITECTURE_SUPPORTED],
|
||||||
on_condition=UpdaterJobError,
|
on_condition=UpdaterJobError,
|
||||||
limit=JobExecutionLimit.THROTTLE_WAIT,
|
limit=JobExecutionLimit.THROTTLE_WAIT,
|
||||||
throttle_period=timedelta(seconds=30),
|
throttle_period=timedelta(seconds=30),
|
||||||
|
43
tests/resolution/evaluation/test_system_architecture.py
Normal file
43
tests/resolution/evaluation/test_system_architecture.py
Normal file
@ -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
|
Loading…
x
Reference in New Issue
Block a user