mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-17 22:26:30 +00:00
Mark CGroup V2 supported on Home Assistant OS (#3778)
* Mark CGroup V2 supported on Home Assistant OS * Fix tests * Fix comparision * Move evaluation of CGroup after OSManager has been initialized
This commit is contained in:
parent
29b2de6998
commit
a92058e6fc
@ -37,6 +37,7 @@ class UnsupportedReason(str, Enum):
|
|||||||
DNS_SERVER = "dns_server"
|
DNS_SERVER = "dns_server"
|
||||||
DOCKER_CONFIGURATION = "docker_configuration"
|
DOCKER_CONFIGURATION = "docker_configuration"
|
||||||
DOCKER_VERSION = "docker_version"
|
DOCKER_VERSION = "docker_version"
|
||||||
|
CGROUP_VERSION = "cgroup_version"
|
||||||
JOB_CONDITIONS = "job_conditions"
|
JOB_CONDITIONS = "job_conditions"
|
||||||
LXC = "lxc"
|
LXC = "lxc"
|
||||||
NETWORK_MANAGER = "network_manager"
|
NETWORK_MANAGER = "network_manager"
|
||||||
|
54
supervisor/resolution/evaluations/cgroup.py
Normal file
54
supervisor/resolution/evaluations/cgroup.py
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
"""Evaluation class for CGroup version."""
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from ...const import CoreState
|
||||||
|
from ...coresys import CoreSys
|
||||||
|
from ..const import UnsupportedReason
|
||||||
|
from .base import EvaluateBase
|
||||||
|
|
||||||
|
CGROUP_V1_VERSION = "1"
|
||||||
|
CGROUP_V2_VERSION = "2"
|
||||||
|
|
||||||
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def setup(coresys: CoreSys) -> EvaluateBase:
|
||||||
|
"""Initialize evaluation-setup function."""
|
||||||
|
return EvaluateCGroupVersion(coresys)
|
||||||
|
|
||||||
|
|
||||||
|
class EvaluateCGroupVersion(EvaluateBase):
|
||||||
|
"""Evaluate Docker configuration."""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def reason(self) -> UnsupportedReason:
|
||||||
|
"""Return a UnsupportedReason enum."""
|
||||||
|
return UnsupportedReason.CGROUP_VERSION
|
||||||
|
|
||||||
|
@property
|
||||||
|
def on_failure(self) -> str:
|
||||||
|
"""Return a string that is printed when self.evaluate is False."""
|
||||||
|
return "The CGroup version used by Docker is not supported"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def states(self) -> list[CoreState]:
|
||||||
|
"""Return a list of valid states when this evaluation can run."""
|
||||||
|
return [CoreState.SETUP]
|
||||||
|
|
||||||
|
async def evaluate(self):
|
||||||
|
"""Run evaluation."""
|
||||||
|
cgroup_version = self.sys_docker.info.cgroup
|
||||||
|
|
||||||
|
expected_version = [CGROUP_V1_VERSION]
|
||||||
|
if self.coresys.os.available:
|
||||||
|
expected_version.append(CGROUP_V2_VERSION)
|
||||||
|
|
||||||
|
if cgroup_version not in expected_version:
|
||||||
|
_LOGGER.warning(
|
||||||
|
"Docker cgroup version %s is not supported! %s",
|
||||||
|
cgroup_version,
|
||||||
|
expected_version,
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
@ -8,7 +8,6 @@ from .base import EvaluateBase
|
|||||||
|
|
||||||
EXPECTED_LOGGING = "journald"
|
EXPECTED_LOGGING = "journald"
|
||||||
EXPECTED_STORAGE = "overlay2"
|
EXPECTED_STORAGE = "overlay2"
|
||||||
EXPECTED_CGROUP_VERSION = "1"
|
|
||||||
|
|
||||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -40,7 +39,6 @@ class EvaluateDockerConfiguration(EvaluateBase):
|
|||||||
"""Run evaluation."""
|
"""Run evaluation."""
|
||||||
storage_driver = self.sys_docker.info.storage
|
storage_driver = self.sys_docker.info.storage
|
||||||
logging_driver = self.sys_docker.info.logging
|
logging_driver = self.sys_docker.info.logging
|
||||||
cgroup_version = self.sys_docker.info.cgroup
|
|
||||||
|
|
||||||
if storage_driver != EXPECTED_STORAGE:
|
if storage_driver != EXPECTED_STORAGE:
|
||||||
_LOGGER.warning(
|
_LOGGER.warning(
|
||||||
@ -52,13 +50,4 @@ class EvaluateDockerConfiguration(EvaluateBase):
|
|||||||
"Docker logging driver %s is not supported!", logging_driver
|
"Docker logging driver %s is not supported!", logging_driver
|
||||||
)
|
)
|
||||||
|
|
||||||
if cgroup_version != EXPECTED_CGROUP_VERSION:
|
return storage_driver != EXPECTED_STORAGE or logging_driver != EXPECTED_LOGGING
|
||||||
_LOGGER.warning(
|
|
||||||
"Docker cgroup version %s is not supported!", cgroup_version
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
|
||||||
storage_driver != EXPECTED_STORAGE
|
|
||||||
or logging_driver != EXPECTED_LOGGING
|
|
||||||
or cgroup_version != EXPECTED_CGROUP_VERSION
|
|
||||||
)
|
|
||||||
|
59
tests/resolution/evaluation/test_evaluate_cgroup.py
Normal file
59
tests/resolution/evaluation/test_evaluate_cgroup.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
"""Test evaluation base."""
|
||||||
|
# pylint: disable=import-error,protected-access
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from supervisor.const import CoreState
|
||||||
|
from supervisor.coresys import CoreSys
|
||||||
|
from supervisor.resolution.evaluations.cgroup import (
|
||||||
|
CGROUP_V1_VERSION,
|
||||||
|
CGROUP_V2_VERSION,
|
||||||
|
EvaluateCGroupVersion,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_evaluation(coresys: CoreSys):
|
||||||
|
"""Test evaluation."""
|
||||||
|
cgroup_version = EvaluateCGroupVersion(coresys)
|
||||||
|
coresys.core.state = CoreState.SETUP
|
||||||
|
|
||||||
|
assert cgroup_version.reason not in coresys.resolution.unsupported
|
||||||
|
|
||||||
|
coresys.docker.info.cgroup = "unsupported"
|
||||||
|
await cgroup_version()
|
||||||
|
assert cgroup_version.reason in coresys.resolution.unsupported
|
||||||
|
coresys.resolution.unsupported.clear()
|
||||||
|
|
||||||
|
coresys.docker.info.cgroup = CGROUP_V2_VERSION
|
||||||
|
coresys.os._available = False
|
||||||
|
await cgroup_version()
|
||||||
|
assert cgroup_version.reason in coresys.resolution.unsupported
|
||||||
|
coresys.resolution.unsupported.clear()
|
||||||
|
|
||||||
|
coresys.docker.info.cgroup = CGROUP_V1_VERSION
|
||||||
|
await cgroup_version()
|
||||||
|
assert cgroup_version.reason not in coresys.resolution.unsupported
|
||||||
|
|
||||||
|
|
||||||
|
async def test_did_run(coresys: CoreSys):
|
||||||
|
"""Test that the evaluation ran as expected."""
|
||||||
|
cgroup_version = EvaluateCGroupVersion(coresys)
|
||||||
|
should_run = cgroup_version.states
|
||||||
|
should_not_run = [state for state in CoreState if state not in should_run]
|
||||||
|
assert len(should_run) != 0
|
||||||
|
assert len(should_not_run) != 0
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"supervisor.resolution.evaluations.cgroup.EvaluateCGroupVersion.evaluate",
|
||||||
|
return_value=None,
|
||||||
|
) as evaluate:
|
||||||
|
for state in should_run:
|
||||||
|
coresys.core.state = state
|
||||||
|
await cgroup_version()
|
||||||
|
evaluate.assert_called_once()
|
||||||
|
evaluate.reset_mock()
|
||||||
|
|
||||||
|
for state in should_not_run:
|
||||||
|
coresys.core.state = state
|
||||||
|
await cgroup_version()
|
||||||
|
evaluate.assert_not_called()
|
||||||
|
evaluate.reset_mock()
|
@ -5,7 +5,6 @@ from unittest.mock import patch
|
|||||||
from supervisor.const import CoreState
|
from supervisor.const import CoreState
|
||||||
from supervisor.coresys import CoreSys
|
from supervisor.coresys import CoreSys
|
||||||
from supervisor.resolution.evaluations.docker_configuration import (
|
from supervisor.resolution.evaluations.docker_configuration import (
|
||||||
EXPECTED_CGROUP_VERSION,
|
|
||||||
EXPECTED_LOGGING,
|
EXPECTED_LOGGING,
|
||||||
EXPECTED_STORAGE,
|
EXPECTED_STORAGE,
|
||||||
EvaluateDockerConfiguration,
|
EvaluateDockerConfiguration,
|
||||||
@ -21,28 +20,18 @@ async def test_evaluation(coresys: CoreSys):
|
|||||||
|
|
||||||
coresys.docker.info.storage = "unsupported"
|
coresys.docker.info.storage = "unsupported"
|
||||||
coresys.docker.info.logging = EXPECTED_LOGGING
|
coresys.docker.info.logging = EXPECTED_LOGGING
|
||||||
coresys.docker.info.cgroup = EXPECTED_CGROUP_VERSION
|
|
||||||
await docker_configuration()
|
await docker_configuration()
|
||||||
assert docker_configuration.reason in coresys.resolution.unsupported
|
assert docker_configuration.reason in coresys.resolution.unsupported
|
||||||
coresys.resolution.unsupported.clear()
|
coresys.resolution.unsupported.clear()
|
||||||
|
|
||||||
coresys.docker.info.storage = EXPECTED_STORAGE
|
coresys.docker.info.storage = EXPECTED_STORAGE
|
||||||
coresys.docker.info.logging = "unsupported"
|
coresys.docker.info.logging = "unsupported"
|
||||||
coresys.docker.info.cgroup = EXPECTED_CGROUP_VERSION
|
|
||||||
await docker_configuration()
|
await docker_configuration()
|
||||||
assert docker_configuration.reason in coresys.resolution.unsupported
|
assert docker_configuration.reason in coresys.resolution.unsupported
|
||||||
coresys.resolution.unsupported.clear()
|
coresys.resolution.unsupported.clear()
|
||||||
|
|
||||||
coresys.docker.info.storage = EXPECTED_STORAGE
|
coresys.docker.info.storage = EXPECTED_STORAGE
|
||||||
coresys.docker.info.logging = EXPECTED_LOGGING
|
coresys.docker.info.logging = EXPECTED_LOGGING
|
||||||
coresys.docker.info.cgroup = "unsupported"
|
|
||||||
await docker_configuration()
|
|
||||||
assert docker_configuration.reason in coresys.resolution.unsupported
|
|
||||||
coresys.resolution.unsupported.clear()
|
|
||||||
|
|
||||||
coresys.docker.info.storage = EXPECTED_STORAGE
|
|
||||||
coresys.docker.info.logging = EXPECTED_LOGGING
|
|
||||||
coresys.docker.info.cgroup = EXPECTED_CGROUP_VERSION
|
|
||||||
await docker_configuration()
|
await docker_configuration()
|
||||||
assert docker_configuration.reason not in coresys.resolution.unsupported
|
assert docker_configuration.reason not in coresys.resolution.unsupported
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user