mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-21 08:06:30 +00:00
Add mount to supported features (#4301)
* Add mount to supported features * Typo in enable * Fix places mocking os available without version * Increase resilence of problematic repeat task test
This commit is contained in:
parent
fbb2776277
commit
f6c3bdb6a8
@ -589,3 +589,7 @@ class MountInvalidError(MountError):
|
|||||||
|
|
||||||
class MountNotFound(MountError):
|
class MountNotFound(MountError):
|
||||||
"""Raise on mount not found."""
|
"""Raise on mount not found."""
|
||||||
|
|
||||||
|
|
||||||
|
class MountJobError(MountError, JobException):
|
||||||
|
"""Raise on Mount job error."""
|
||||||
|
@ -46,6 +46,7 @@ class HostFeature(str, Enum):
|
|||||||
HAOS = "haos"
|
HAOS = "haos"
|
||||||
HOSTNAME = "hostname"
|
HOSTNAME = "hostname"
|
||||||
JOURNAL = "journal"
|
JOURNAL = "journal"
|
||||||
|
MOUNT = "mount"
|
||||||
NETWORK = "network"
|
NETWORK = "network"
|
||||||
OS_AGENT = "os_agent"
|
OS_AGENT = "os_agent"
|
||||||
REBOOT = "reboot"
|
REBOOT = "reboot"
|
||||||
|
@ -3,7 +3,7 @@ from contextlib import suppress
|
|||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from supervisor.host.logs import LogsControl
|
from awesomeversion import AwesomeVersion
|
||||||
|
|
||||||
from ..const import BusEvent
|
from ..const import BusEvent
|
||||||
from ..coresys import CoreSys, CoreSysAttributes
|
from ..coresys import CoreSys, CoreSysAttributes
|
||||||
@ -14,6 +14,7 @@ from .apparmor import AppArmorControl
|
|||||||
from .const import HostFeature
|
from .const import HostFeature
|
||||||
from .control import SystemControl
|
from .control import SystemControl
|
||||||
from .info import InfoCenter
|
from .info import InfoCenter
|
||||||
|
from .logs import LogsControl
|
||||||
from .network import NetworkManager
|
from .network import NetworkManager
|
||||||
from .services import ServiceManager
|
from .services import ServiceManager
|
||||||
from .sound import SoundControl
|
from .sound import SoundControl
|
||||||
@ -110,6 +111,12 @@ class HostManager(CoreSysAttributes):
|
|||||||
if self.sys_dbus.udisks2.is_connected:
|
if self.sys_dbus.udisks2.is_connected:
|
||||||
features.append(HostFeature.DISK)
|
features.append(HostFeature.DISK)
|
||||||
|
|
||||||
|
# Support added in OS10. For supervised, assume they can if systemd is connected
|
||||||
|
if self.sys_dbus.systemd.is_connected and (
|
||||||
|
not self.sys_os.available or self.sys_os.version >= AwesomeVersion("10")
|
||||||
|
):
|
||||||
|
features.append(HostFeature.MOUNT)
|
||||||
|
|
||||||
return features
|
return features
|
||||||
|
|
||||||
async def reload(self):
|
async def reload(self):
|
||||||
|
@ -19,6 +19,7 @@ class JobCondition(str, Enum):
|
|||||||
HOST_NETWORK = "host_network"
|
HOST_NETWORK = "host_network"
|
||||||
INTERNET_HOST = "internet_host"
|
INTERNET_HOST = "internet_host"
|
||||||
INTERNET_SYSTEM = "internet_system"
|
INTERNET_SYSTEM = "internet_system"
|
||||||
|
MOUNT_AVAILABLE = "mount_available"
|
||||||
OS_AGENT = "os_agent"
|
OS_AGENT = "os_agent"
|
||||||
PLUGINS_UPDATED = "plugins_updated"
|
PLUGINS_UPDATED = "plugins_updated"
|
||||||
RUNNING = "running"
|
RUNNING = "running"
|
||||||
|
@ -269,6 +269,14 @@ class Job(CoreSysAttributes):
|
|||||||
f"'{self._method.__qualname__}' blocked from execution, was unable to update plugin(s) {', '.join(update_failures)} and all plugins must be up to date first"
|
f"'{self._method.__qualname__}' blocked from execution, was unable to update plugin(s) {', '.join(update_failures)} and all plugins must be up to date first"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (
|
||||||
|
JobCondition.MOUNT_AVAILABLE in used_conditions
|
||||||
|
and HostFeature.MOUNT not in self.sys_host.features
|
||||||
|
):
|
||||||
|
raise JobConditionException(
|
||||||
|
f"'{self._method.__qualname__}' blocked from execution, mounting not supported on system"
|
||||||
|
)
|
||||||
|
|
||||||
async def _acquire_exection_limit(self) -> None:
|
async def _acquire_exection_limit(self) -> None:
|
||||||
"""Process exection limits."""
|
"""Process exection limits."""
|
||||||
if self.limit not in (
|
if self.limit not in (
|
||||||
|
@ -9,7 +9,10 @@ from pathlib import PurePath
|
|||||||
from ..const import ATTR_NAME
|
from ..const import ATTR_NAME
|
||||||
from ..coresys import CoreSys, CoreSysAttributes
|
from ..coresys import CoreSys, CoreSysAttributes
|
||||||
from ..dbus.const import UnitActiveState
|
from ..dbus.const import UnitActiveState
|
||||||
from ..exceptions import MountActivationError, MountError, MountNotFound
|
from ..exceptions import MountActivationError, MountError, MountJobError, MountNotFound
|
||||||
|
from ..host.const import HostFeature
|
||||||
|
from ..jobs.const import JobCondition
|
||||||
|
from ..jobs.decorator import Job
|
||||||
from ..resolution.const import SuggestionType
|
from ..resolution.const import SuggestionType
|
||||||
from ..utils.common import FileConfiguration
|
from ..utils.common import FileConfiguration
|
||||||
from ..utils.sentry import capture_exception
|
from ..utils.sentry import capture_exception
|
||||||
@ -102,6 +105,12 @@ class MountManager(FileConfiguration, CoreSysAttributes):
|
|||||||
if not self.mounts:
|
if not self.mounts:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if HostFeature.MOUNT not in self.sys_host.features:
|
||||||
|
_LOGGER.error(
|
||||||
|
"Cannot load configured mounts because mounting not supported on system!"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
_LOGGER.info("Initializing all user-configured mounts")
|
_LOGGER.info("Initializing all user-configured mounts")
|
||||||
await self._mount_errors_to_issues(
|
await self._mount_errors_to_issues(
|
||||||
self.mounts.copy(), [mount.load() for mount in self.mounts]
|
self.mounts.copy(), [mount.load() for mount in self.mounts]
|
||||||
@ -116,6 +125,7 @@ class MountManager(FileConfiguration, CoreSysAttributes):
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Job(conditions=[JobCondition.MOUNT_AVAILABLE])
|
||||||
async def reload(self) -> None:
|
async def reload(self) -> None:
|
||||||
"""Update mounts info via dbus and reload failed mounts."""
|
"""Update mounts info via dbus and reload failed mounts."""
|
||||||
await asyncio.wait(
|
await asyncio.wait(
|
||||||
@ -153,6 +163,7 @@ class MountManager(FileConfiguration, CoreSysAttributes):
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Job(conditions=[JobCondition.MOUNT_AVAILABLE], on_condition=MountJobError)
|
||||||
async def create_mount(self, mount: Mount) -> None:
|
async def create_mount(self, mount: Mount) -> None:
|
||||||
"""Add/update a mount."""
|
"""Add/update a mount."""
|
||||||
if mount.name in self._mounts:
|
if mount.name in self._mounts:
|
||||||
@ -170,6 +181,7 @@ class MountManager(FileConfiguration, CoreSysAttributes):
|
|||||||
if mount.usage == MountUsage.MEDIA:
|
if mount.usage == MountUsage.MEDIA:
|
||||||
await self._bind_media(mount)
|
await self._bind_media(mount)
|
||||||
|
|
||||||
|
@Job(conditions=[JobCondition.MOUNT_AVAILABLE], on_condition=MountJobError)
|
||||||
async def remove_mount(self, name: str, *, retain_entry: bool = False) -> None:
|
async def remove_mount(self, name: str, *, retain_entry: bool = False) -> None:
|
||||||
"""Remove a mount."""
|
"""Remove a mount."""
|
||||||
if name not in self._mounts:
|
if name not in self._mounts:
|
||||||
@ -192,6 +204,7 @@ class MountManager(FileConfiguration, CoreSysAttributes):
|
|||||||
|
|
||||||
return mount
|
return mount
|
||||||
|
|
||||||
|
@Job(conditions=[JobCondition.MOUNT_AVAILABLE], on_condition=MountJobError)
|
||||||
async def reload_mount(self, name: str) -> None:
|
async def reload_mount(self, name: str) -> None:
|
||||||
"""Reload a mount to retry mounting with same config."""
|
"""Reload a mount to retry mounting with same config."""
|
||||||
if name not in self._mounts:
|
if name not in self._mounts:
|
||||||
|
@ -158,6 +158,32 @@ async def test_api_create_dbus_error_mount_not_added(
|
|||||||
assert result["data"]["mounts"] == []
|
assert result["data"]["mounts"] == []
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("os_available", ["9.5"], indirect=True)
|
||||||
|
async def test_api_create_mount_fails_not_supported_feature(
|
||||||
|
api_client: TestClient,
|
||||||
|
coresys: CoreSys,
|
||||||
|
os_available,
|
||||||
|
):
|
||||||
|
"""Test creating a mount via API fails when mounting isn't a supported feature on system.."""
|
||||||
|
resp = await api_client.post(
|
||||||
|
"/mounts",
|
||||||
|
json={
|
||||||
|
"name": "backup_test",
|
||||||
|
"type": "cifs",
|
||||||
|
"usage": "backup",
|
||||||
|
"server": "backup.local",
|
||||||
|
"share": "backups",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
assert resp.status == 400
|
||||||
|
result = await resp.json()
|
||||||
|
assert result["result"] == "error"
|
||||||
|
assert (
|
||||||
|
result["message"]
|
||||||
|
== "'MountManager.create_mount' blocked from execution, mounting not supported on system"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def test_api_update_mount(api_client: TestClient, coresys: CoreSys, mount):
|
async def test_api_update_mount(api_client: TestClient, coresys: CoreSys, mount):
|
||||||
"""Test updating a mount via API."""
|
"""Test updating a mount via API."""
|
||||||
resp = await api_client.put(
|
resp = await api_client.put(
|
||||||
|
@ -17,8 +17,6 @@ from tests.dbus_service_mocks.agent_boards_yellow import Yellow as YellowService
|
|||||||
from tests.dbus_service_mocks.agent_datadisk import DataDisk as DataDiskService
|
from tests.dbus_service_mocks.agent_datadisk import DataDisk as DataDiskService
|
||||||
from tests.dbus_service_mocks.base import DBusServiceMock
|
from tests.dbus_service_mocks.base import DBusServiceMock
|
||||||
|
|
||||||
# pylint: disable=protected-access
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(name="boards_service")
|
@pytest.fixture(name="boards_service")
|
||||||
async def fixture_boards_service(
|
async def fixture_boards_service(
|
||||||
@ -58,11 +56,12 @@ async def test_api_os_info_with_agent(api_client: TestClient, coresys: CoreSys):
|
|||||||
ids=["non-existent", "unavailable drive by path", "unavailable drive by id"],
|
ids=["non-existent", "unavailable drive by path", "unavailable drive by id"],
|
||||||
)
|
)
|
||||||
async def test_api_os_datadisk_move_fail(
|
async def test_api_os_datadisk_move_fail(
|
||||||
api_client: TestClient, coresys: CoreSys, new_disk: str
|
api_client: TestClient,
|
||||||
|
coresys: CoreSys,
|
||||||
|
new_disk: str,
|
||||||
|
os_available,
|
||||||
):
|
):
|
||||||
"""Test datadisk move to non-existent or invalid devices."""
|
"""Test datadisk move to non-existent or invalid devices."""
|
||||||
coresys.os._available = True
|
|
||||||
|
|
||||||
resp = await api_client.post("/os/datadisk/move", json={"device": new_disk})
|
resp = await api_client.post("/os/datadisk/move", json={"device": new_disk})
|
||||||
result = await resp.json()
|
result = await resp.json()
|
||||||
|
|
||||||
@ -98,11 +97,11 @@ async def test_api_os_datadisk_migrate(
|
|||||||
coresys: CoreSys,
|
coresys: CoreSys,
|
||||||
os_agent_services: dict[str, DBusServiceMock],
|
os_agent_services: dict[str, DBusServiceMock],
|
||||||
new_disk: str,
|
new_disk: str,
|
||||||
|
os_available,
|
||||||
):
|
):
|
||||||
"""Test migrating datadisk."""
|
"""Test migrating datadisk."""
|
||||||
datadisk_service: DataDiskService = os_agent_services["agent_datadisk"]
|
datadisk_service: DataDiskService = os_agent_services["agent_datadisk"]
|
||||||
datadisk_service.ChangeDevice.calls.clear()
|
datadisk_service.ChangeDevice.calls.clear()
|
||||||
coresys.os._available = True
|
|
||||||
|
|
||||||
with patch.object(SystemControl, "reboot") as reboot:
|
with patch.object(SystemControl, "reboot") as reboot:
|
||||||
resp = await api_client.post("/os/datadisk/move", json={"device": new_disk})
|
resp = await api_client.post("/os/datadisk/move", json={"device": new_disk})
|
||||||
|
@ -42,6 +42,7 @@ from supervisor.dbus.network import NetworkManager
|
|||||||
from supervisor.docker.manager import DockerAPI
|
from supervisor.docker.manager import DockerAPI
|
||||||
from supervisor.docker.monitor import DockerMonitor
|
from supervisor.docker.monitor import DockerMonitor
|
||||||
from supervisor.host.logs import LogsControl
|
from supervisor.host.logs import LogsControl
|
||||||
|
from supervisor.os.manager import OSManager
|
||||||
from supervisor.store.addon import AddonStore
|
from supervisor.store.addon import AddonStore
|
||||||
from supervisor.store.repository import Repository
|
from supervisor.store.repository import Repository
|
||||||
from supervisor.utils.dt import utcnow
|
from supervisor.utils.dt import utcnow
|
||||||
@ -602,3 +603,17 @@ async def capture_exception() -> Mock:
|
|||||||
"supervisor.utils.sentry.sentry_sdk.capture_exception"
|
"supervisor.utils.sentry.sentry_sdk.capture_exception"
|
||||||
) as capture_exception:
|
) as capture_exception:
|
||||||
yield capture_exception
|
yield capture_exception
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
async def os_available(request: pytest.FixtureRequest) -> None:
|
||||||
|
"""Mock os as available."""
|
||||||
|
version = (
|
||||||
|
AwesomeVersion(request.param)
|
||||||
|
if hasattr(request, "param")
|
||||||
|
else AwesomeVersion("10.0")
|
||||||
|
)
|
||||||
|
with patch.object(
|
||||||
|
OSManager, "available", new=PropertyMock(return_value=True)
|
||||||
|
), patch.object(OSManager, "version", new=PropertyMock(return_value=version)):
|
||||||
|
yield
|
||||||
|
@ -29,7 +29,11 @@ async def test_simple_task_repeat(coresys):
|
|||||||
trigger.append(True)
|
trigger.append(True)
|
||||||
|
|
||||||
coresys.scheduler.register_task(test_task, 0.1, True)
|
coresys.scheduler.register_task(test_task, 0.1, True)
|
||||||
await asyncio.sleep(0.3)
|
|
||||||
|
for _ in range(5):
|
||||||
|
await asyncio.sleep(0.1)
|
||||||
|
if len(trigger) > 1:
|
||||||
|
break
|
||||||
|
|
||||||
assert len(trigger) > 1
|
assert len(trigger) > 1
|
||||||
|
|
||||||
|
@ -10,7 +10,12 @@ import pytest
|
|||||||
|
|
||||||
from supervisor.coresys import CoreSys
|
from supervisor.coresys import CoreSys
|
||||||
from supervisor.dbus.const import UnitActiveState
|
from supervisor.dbus.const import UnitActiveState
|
||||||
from supervisor.exceptions import MountActivationError, MountError, MountNotFound
|
from supervisor.exceptions import (
|
||||||
|
MountActivationError,
|
||||||
|
MountError,
|
||||||
|
MountJobError,
|
||||||
|
MountNotFound,
|
||||||
|
)
|
||||||
from supervisor.mounts.manager import MountManager
|
from supervisor.mounts.manager import MountManager
|
||||||
from supervisor.mounts.mount import Mount
|
from supervisor.mounts.mount import Mount
|
||||||
from supervisor.resolution.const import ContextType, IssueType, SuggestionType
|
from supervisor.resolution.const import ContextType, IssueType, SuggestionType
|
||||||
@ -506,3 +511,33 @@ async def test_reload_mounts(
|
|||||||
assert mount.state == UnitActiveState.ACTIVE
|
assert mount.state == UnitActiveState.ACTIVE
|
||||||
assert mount.failed_issue not in coresys.resolution.issues
|
assert mount.failed_issue not in coresys.resolution.issues
|
||||||
assert not coresys.resolution.suggestions_for_issue(mount.failed_issue)
|
assert not coresys.resolution.suggestions_for_issue(mount.failed_issue)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("os_available", ["9.5"], indirect=True)
|
||||||
|
async def test_mounting_not_supported(
|
||||||
|
coresys: CoreSys,
|
||||||
|
caplog: pytest.LogCaptureFixture,
|
||||||
|
os_available,
|
||||||
|
):
|
||||||
|
"""Test mounting not supported on system."""
|
||||||
|
caplog.clear()
|
||||||
|
|
||||||
|
await coresys.mounts.load()
|
||||||
|
assert not caplog.text
|
||||||
|
|
||||||
|
mount = Mount.from_dict(coresys, MEDIA_TEST_DATA)
|
||||||
|
coresys.mounts._mounts = {"media_test": mount} # pylint: disable=protected-access
|
||||||
|
|
||||||
|
# Only tell the user about an issue here if they actually have mounts we couldn't load
|
||||||
|
# This is an edge case but users can downgrade OS so its possible
|
||||||
|
await coresys.mounts.load()
|
||||||
|
assert "Cannot load configured mounts" in caplog.text
|
||||||
|
|
||||||
|
with pytest.raises(MountJobError):
|
||||||
|
await coresys.mounts.create_mount(mount)
|
||||||
|
|
||||||
|
with pytest.raises(MountJobError):
|
||||||
|
await coresys.mounts.reload_mount("media_test")
|
||||||
|
|
||||||
|
with pytest.raises(MountJobError):
|
||||||
|
await coresys.mounts.remove_mount("media_test")
|
||||||
|
@ -22,8 +22,6 @@ from tests.dbus_service_mocks.udisks2_partition_table import (
|
|||||||
PartitionTable as PartitionTableService,
|
PartitionTable as PartitionTableService,
|
||||||
)
|
)
|
||||||
|
|
||||||
# pylint: disable=protected-access
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
async def add_unusable_drive(
|
async def add_unusable_drive(
|
||||||
@ -70,10 +68,8 @@ async def tests_datadisk_current(coresys: CoreSys):
|
|||||||
["/dev/sdaaaa", "/dev/mmcblk1", "Generic-Flash-Disk-61BCDDB6"],
|
["/dev/sdaaaa", "/dev/mmcblk1", "Generic-Flash-Disk-61BCDDB6"],
|
||||||
ids=["non-existent", "unavailable drive by path", "unavailable drive by id"],
|
ids=["non-existent", "unavailable drive by path", "unavailable drive by id"],
|
||||||
)
|
)
|
||||||
async def test_datadisk_move_fail(coresys: CoreSys, new_disk: str):
|
async def test_datadisk_move_fail(coresys: CoreSys, new_disk: str, os_available):
|
||||||
"""Test datadisk move to non-existent or invalid devices."""
|
"""Test datadisk move to non-existent or invalid devices."""
|
||||||
coresys.os._available = True
|
|
||||||
|
|
||||||
with pytest.raises(
|
with pytest.raises(
|
||||||
HassOSDataDiskError, match=f"'{new_disk}' not a valid data disk target!"
|
HassOSDataDiskError, match=f"'{new_disk}' not a valid data disk target!"
|
||||||
):
|
):
|
||||||
@ -112,13 +108,13 @@ async def test_datadisk_migrate(
|
|||||||
coresys: CoreSys,
|
coresys: CoreSys,
|
||||||
all_dbus_services: dict[str, DBusServiceMock | dict[str, DBusServiceMock]],
|
all_dbus_services: dict[str, DBusServiceMock | dict[str, DBusServiceMock]],
|
||||||
new_disk: str,
|
new_disk: str,
|
||||||
|
os_available,
|
||||||
):
|
):
|
||||||
"""Test migrating data disk."""
|
"""Test migrating data disk."""
|
||||||
datadisk_service: DataDiskService = all_dbus_services["agent_datadisk"]
|
datadisk_service: DataDiskService = all_dbus_services["agent_datadisk"]
|
||||||
datadisk_service.ChangeDevice.calls.clear()
|
datadisk_service.ChangeDevice.calls.clear()
|
||||||
logind_service: LogindService = all_dbus_services["logind"]
|
logind_service: LogindService = all_dbus_services["logind"]
|
||||||
logind_service.Reboot.calls.clear()
|
logind_service.Reboot.calls.clear()
|
||||||
coresys.os._available = True
|
|
||||||
|
|
||||||
with patch.object(Core, "shutdown") as shutdown:
|
with patch.object(Core, "shutdown") as shutdown:
|
||||||
await coresys.os.datadisk.migrate_disk(new_disk)
|
await coresys.os.datadisk.migrate_disk(new_disk)
|
||||||
@ -137,6 +133,7 @@ async def test_datadisk_migrate_mark_data_move(
|
|||||||
coresys: CoreSys,
|
coresys: CoreSys,
|
||||||
all_dbus_services: dict[str, DBusServiceMock | dict[str, DBusServiceMock]],
|
all_dbus_services: dict[str, DBusServiceMock | dict[str, DBusServiceMock]],
|
||||||
new_disk: str,
|
new_disk: str,
|
||||||
|
os_available,
|
||||||
):
|
):
|
||||||
"""Test migrating data disk with os agent 1.5.0 or later."""
|
"""Test migrating data disk with os agent 1.5.0 or later."""
|
||||||
datadisk_service: DataDiskService = all_dbus_services["agent_datadisk"]
|
datadisk_service: DataDiskService = all_dbus_services["agent_datadisk"]
|
||||||
@ -155,7 +152,6 @@ async def test_datadisk_migrate_mark_data_move(
|
|||||||
|
|
||||||
all_dbus_services["os_agent"].emit_properties_changed({"Version": "1.5.0"})
|
all_dbus_services["os_agent"].emit_properties_changed({"Version": "1.5.0"})
|
||||||
await all_dbus_services["os_agent"].ping()
|
await all_dbus_services["os_agent"].ping()
|
||||||
coresys.os._available = True
|
|
||||||
|
|
||||||
with patch.object(Core, "shutdown") as shutdown:
|
with patch.object(Core, "shutdown") as shutdown:
|
||||||
await coresys.os.datadisk.migrate_disk(new_disk)
|
await coresys.os.datadisk.migrate_disk(new_disk)
|
||||||
@ -181,6 +177,7 @@ async def test_datadisk_migrate_mark_data_move(
|
|||||||
async def test_datadisk_migrate_too_small(
|
async def test_datadisk_migrate_too_small(
|
||||||
coresys: CoreSys,
|
coresys: CoreSys,
|
||||||
all_dbus_services: dict[str, DBusServiceMock | dict[str, DBusServiceMock]],
|
all_dbus_services: dict[str, DBusServiceMock | dict[str, DBusServiceMock]],
|
||||||
|
os_available,
|
||||||
):
|
):
|
||||||
"""Test migration stops and exits if new partition is too small."""
|
"""Test migration stops and exits if new partition is too small."""
|
||||||
datadisk_service: DataDiskService = all_dbus_services["agent_datadisk"]
|
datadisk_service: DataDiskService = all_dbus_services["agent_datadisk"]
|
||||||
@ -198,7 +195,6 @@ async def test_datadisk_migrate_too_small(
|
|||||||
|
|
||||||
all_dbus_services["os_agent"].emit_properties_changed({"Version": "1.5.0"})
|
all_dbus_services["os_agent"].emit_properties_changed({"Version": "1.5.0"})
|
||||||
await all_dbus_services["os_agent"].ping()
|
await all_dbus_services["os_agent"].ping()
|
||||||
coresys.os._available = True
|
|
||||||
|
|
||||||
with pytest.raises(
|
with pytest.raises(
|
||||||
HassOSDataDiskError,
|
HassOSDataDiskError,
|
||||||
@ -214,6 +210,7 @@ async def test_datadisk_migrate_too_small(
|
|||||||
async def test_datadisk_migrate_multiple_external_data_disks(
|
async def test_datadisk_migrate_multiple_external_data_disks(
|
||||||
coresys: CoreSys,
|
coresys: CoreSys,
|
||||||
all_dbus_services: dict[str, DBusServiceMock | dict[str, DBusServiceMock]],
|
all_dbus_services: dict[str, DBusServiceMock | dict[str, DBusServiceMock]],
|
||||||
|
os_available,
|
||||||
):
|
):
|
||||||
"""Test migration stops when another hassos-data-external partition detected."""
|
"""Test migration stops when another hassos-data-external partition detected."""
|
||||||
datadisk_service: DataDiskService = all_dbus_services["agent_datadisk"]
|
datadisk_service: DataDiskService = all_dbus_services["agent_datadisk"]
|
||||||
@ -226,7 +223,6 @@ async def test_datadisk_migrate_multiple_external_data_disks(
|
|||||||
sdb1_filesystem_service.fixture = replace(
|
sdb1_filesystem_service.fixture = replace(
|
||||||
sdb1_filesystem_service.fixture, MountPoints=[]
|
sdb1_filesystem_service.fixture, MountPoints=[]
|
||||||
)
|
)
|
||||||
coresys.os._available = True
|
|
||||||
|
|
||||||
with pytest.raises(
|
with pytest.raises(
|
||||||
HassOSDataDiskError,
|
HassOSDataDiskError,
|
||||||
@ -241,6 +237,7 @@ async def test_datadisk_migrate_multiple_external_data_disks(
|
|||||||
async def test_datadisk_migrate_between_external_renames(
|
async def test_datadisk_migrate_between_external_renames(
|
||||||
coresys: CoreSys,
|
coresys: CoreSys,
|
||||||
all_dbus_services: dict[str, DBusServiceMock | dict[str, DBusServiceMock]],
|
all_dbus_services: dict[str, DBusServiceMock | dict[str, DBusServiceMock]],
|
||||||
|
os_available,
|
||||||
):
|
):
|
||||||
"""Test migration from one external data disk to another renames the original."""
|
"""Test migration from one external data disk to another renames the original."""
|
||||||
sdb1_partition_service: PartitionService = all_dbus_services["udisks2_partition"][
|
sdb1_partition_service: PartitionService = all_dbus_services["udisks2_partition"][
|
||||||
@ -266,7 +263,6 @@ async def test_datadisk_migrate_between_external_renames(
|
|||||||
|
|
||||||
all_dbus_services["os_agent"].emit_properties_changed({"Version": "1.5.0"})
|
all_dbus_services["os_agent"].emit_properties_changed({"Version": "1.5.0"})
|
||||||
await all_dbus_services["os_agent"].ping()
|
await all_dbus_services["os_agent"].ping()
|
||||||
coresys.os._available = True
|
|
||||||
|
|
||||||
await coresys.os.datadisk.migrate_disk("Generic-Flash-Disk-61BCDDB6")
|
await coresys.os.datadisk.migrate_disk("Generic-Flash-Disk-61BCDDB6")
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
"""Test evaluation base."""
|
"""Test evaluation base."""
|
||||||
# pylint: disable=import-error,protected-access
|
# pylint: disable=import-error
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from supervisor.const import CoreState
|
from supervisor.const import CoreState
|
||||||
@ -24,7 +24,6 @@ async def test_evaluation(coresys: CoreSys):
|
|||||||
coresys.resolution.unsupported.clear()
|
coresys.resolution.unsupported.clear()
|
||||||
|
|
||||||
coresys.docker.info.cgroup = CGROUP_V2_VERSION
|
coresys.docker.info.cgroup = CGROUP_V2_VERSION
|
||||||
coresys.os._available = False
|
|
||||||
await cgroup_version()
|
await cgroup_version()
|
||||||
assert cgroup_version.reason in coresys.resolution.unsupported
|
assert cgroup_version.reason in coresys.resolution.unsupported
|
||||||
coresys.resolution.unsupported.clear()
|
coresys.resolution.unsupported.clear()
|
||||||
@ -34,12 +33,11 @@ async def test_evaluation(coresys: CoreSys):
|
|||||||
assert cgroup_version.reason not in coresys.resolution.unsupported
|
assert cgroup_version.reason not in coresys.resolution.unsupported
|
||||||
|
|
||||||
|
|
||||||
async def test_evaluation_os_available(coresys: CoreSys):
|
async def test_evaluation_os_available(coresys: CoreSys, os_available):
|
||||||
"""Test evaluation with OS available."""
|
"""Test evaluation with OS available."""
|
||||||
cgroup_version = EvaluateCGroupVersion(coresys)
|
cgroup_version = EvaluateCGroupVersion(coresys)
|
||||||
coresys.core.state = CoreState.SETUP
|
coresys.core.state = CoreState.SETUP
|
||||||
|
|
||||||
coresys.os._available = True
|
|
||||||
coresys.docker.info.cgroup = CGROUP_V2_VERSION
|
coresys.docker.info.cgroup = CGROUP_V2_VERSION
|
||||||
await cgroup_version()
|
await cgroup_version()
|
||||||
assert cgroup_version.reason not in coresys.resolution.unsupported
|
assert cgroup_version.reason not in coresys.resolution.unsupported
|
||||||
|
Loading…
x
Reference in New Issue
Block a user