mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 20:57:21 +00:00
Allow backup writer to update progress during restore (#135975)
* Allow backup writer to update progress during restore * Clarify comment
This commit is contained in:
parent
43da828a51
commit
760168de83
@ -27,6 +27,7 @@ from .manager import (
|
|||||||
IncorrectPasswordError,
|
IncorrectPasswordError,
|
||||||
ManagerBackup,
|
ManagerBackup,
|
||||||
NewBackup,
|
NewBackup,
|
||||||
|
RestoreBackupEvent,
|
||||||
WrittenBackup,
|
WrittenBackup,
|
||||||
)
|
)
|
||||||
from .models import AddonInfo, AgentBackup, Folder
|
from .models import AddonInfo, AgentBackup, Folder
|
||||||
@ -47,6 +48,7 @@ __all__ = [
|
|||||||
"LocalBackupAgent",
|
"LocalBackupAgent",
|
||||||
"ManagerBackup",
|
"ManagerBackup",
|
||||||
"NewBackup",
|
"NewBackup",
|
||||||
|
"RestoreBackupEvent",
|
||||||
"WrittenBackup",
|
"WrittenBackup",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -147,6 +147,7 @@ class RestoreBackupState(StrEnum):
|
|||||||
"""Receive backup state enum."""
|
"""Receive backup state enum."""
|
||||||
|
|
||||||
COMPLETED = "completed"
|
COMPLETED = "completed"
|
||||||
|
CORE_RESTART = "core_restart"
|
||||||
FAILED = "failed"
|
FAILED = "failed"
|
||||||
IN_PROGRESS = "in_progress"
|
IN_PROGRESS = "in_progress"
|
||||||
|
|
||||||
@ -217,7 +218,7 @@ class BackupReaderWriter(abc.ABC):
|
|||||||
include_database: bool,
|
include_database: bool,
|
||||||
include_folders: list[Folder] | None,
|
include_folders: list[Folder] | None,
|
||||||
include_homeassistant: bool,
|
include_homeassistant: bool,
|
||||||
on_progress: Callable[[ManagerStateEvent], None],
|
on_progress: Callable[[CreateBackupEvent], None],
|
||||||
password: str | None,
|
password: str | None,
|
||||||
) -> tuple[NewBackup, asyncio.Task[WrittenBackup]]:
|
) -> tuple[NewBackup, asyncio.Task[WrittenBackup]]:
|
||||||
"""Create a backup."""
|
"""Create a backup."""
|
||||||
@ -238,6 +239,7 @@ class BackupReaderWriter(abc.ABC):
|
|||||||
backup_id: str,
|
backup_id: str,
|
||||||
*,
|
*,
|
||||||
agent_id: str,
|
agent_id: str,
|
||||||
|
on_progress: Callable[[RestoreBackupEvent], None],
|
||||||
open_stream: Callable[[], Coroutine[Any, Any, AsyncIterator[bytes]]],
|
open_stream: Callable[[], Coroutine[Any, Any, AsyncIterator[bytes]]],
|
||||||
password: str | None,
|
password: str | None,
|
||||||
restore_addons: list[str] | None,
|
restore_addons: list[str] | None,
|
||||||
@ -941,6 +943,7 @@ class BackupManager:
|
|||||||
backup_id=backup_id,
|
backup_id=backup_id,
|
||||||
open_stream=open_backup,
|
open_stream=open_backup,
|
||||||
agent_id=agent_id,
|
agent_id=agent_id,
|
||||||
|
on_progress=self.async_on_backup_event,
|
||||||
password=password,
|
password=password,
|
||||||
restore_addons=restore_addons,
|
restore_addons=restore_addons,
|
||||||
restore_database=restore_database,
|
restore_database=restore_database,
|
||||||
@ -1130,7 +1133,7 @@ class CoreBackupReaderWriter(BackupReaderWriter):
|
|||||||
include_database: bool,
|
include_database: bool,
|
||||||
include_folders: list[Folder] | None,
|
include_folders: list[Folder] | None,
|
||||||
include_homeassistant: bool,
|
include_homeassistant: bool,
|
||||||
on_progress: Callable[[ManagerStateEvent], None],
|
on_progress: Callable[[CreateBackupEvent], None],
|
||||||
password: str | None,
|
password: str | None,
|
||||||
) -> tuple[NewBackup, asyncio.Task[WrittenBackup]]:
|
) -> tuple[NewBackup, asyncio.Task[WrittenBackup]]:
|
||||||
"""Initiate generating a backup."""
|
"""Initiate generating a backup."""
|
||||||
@ -1170,7 +1173,7 @@ class CoreBackupReaderWriter(BackupReaderWriter):
|
|||||||
date_str: str,
|
date_str: str,
|
||||||
extra_metadata: dict[str, bool | str],
|
extra_metadata: dict[str, bool | str],
|
||||||
include_database: bool,
|
include_database: bool,
|
||||||
on_progress: Callable[[ManagerStateEvent], None],
|
on_progress: Callable[[CreateBackupEvent], None],
|
||||||
password: str | None,
|
password: str | None,
|
||||||
) -> WrittenBackup:
|
) -> WrittenBackup:
|
||||||
"""Generate a backup."""
|
"""Generate a backup."""
|
||||||
@ -1378,6 +1381,7 @@ class CoreBackupReaderWriter(BackupReaderWriter):
|
|||||||
open_stream: Callable[[], Coroutine[Any, Any, AsyncIterator[bytes]]],
|
open_stream: Callable[[], Coroutine[Any, Any, AsyncIterator[bytes]]],
|
||||||
*,
|
*,
|
||||||
agent_id: str,
|
agent_id: str,
|
||||||
|
on_progress: Callable[[RestoreBackupEvent], None],
|
||||||
password: str | None,
|
password: str | None,
|
||||||
restore_addons: list[str] | None,
|
restore_addons: list[str] | None,
|
||||||
restore_database: bool,
|
restore_database: bool,
|
||||||
@ -1440,6 +1444,9 @@ class CoreBackupReaderWriter(BackupReaderWriter):
|
|||||||
)
|
)
|
||||||
|
|
||||||
await self._hass.async_add_executor_job(_write_restore_file)
|
await self._hass.async_add_executor_job(_write_restore_file)
|
||||||
|
on_progress(
|
||||||
|
RestoreBackupEvent(stage=None, state=RestoreBackupState.CORE_RESTART)
|
||||||
|
)
|
||||||
await self._hass.services.async_call("homeassistant", "restart", blocking=True)
|
await self._hass.services.async_call("homeassistant", "restart", blocking=True)
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ from homeassistant.components.backup import (
|
|||||||
Folder,
|
Folder,
|
||||||
IncorrectPasswordError,
|
IncorrectPasswordError,
|
||||||
NewBackup,
|
NewBackup,
|
||||||
|
RestoreBackupEvent,
|
||||||
WrittenBackup,
|
WrittenBackup,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
@ -275,7 +276,7 @@ class SupervisorBackupReaderWriter(BackupReaderWriter):
|
|||||||
backup_id: str | None = None
|
backup_id: str | None = None
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def on_progress(data: Mapping[str, Any]) -> None:
|
def on_job_progress(data: Mapping[str, Any]) -> None:
|
||||||
"""Handle backup progress."""
|
"""Handle backup progress."""
|
||||||
nonlocal backup_id
|
nonlocal backup_id
|
||||||
if data.get("done") is True:
|
if data.get("done") is True:
|
||||||
@ -283,7 +284,7 @@ class SupervisorBackupReaderWriter(BackupReaderWriter):
|
|||||||
backup_complete.set()
|
backup_complete.set()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
unsub = self._async_listen_job_events(backup.job_id, on_progress)
|
unsub = self._async_listen_job_events(backup.job_id, on_job_progress)
|
||||||
await backup_complete.wait()
|
await backup_complete.wait()
|
||||||
finally:
|
finally:
|
||||||
unsub()
|
unsub()
|
||||||
@ -374,6 +375,7 @@ class SupervisorBackupReaderWriter(BackupReaderWriter):
|
|||||||
backup_id: str,
|
backup_id: str,
|
||||||
*,
|
*,
|
||||||
agent_id: str,
|
agent_id: str,
|
||||||
|
on_progress: Callable[[RestoreBackupEvent], None],
|
||||||
open_stream: Callable[[], Coroutine[Any, Any, AsyncIterator[bytes]]],
|
open_stream: Callable[[], Coroutine[Any, Any, AsyncIterator[bytes]]],
|
||||||
password: str | None,
|
password: str | None,
|
||||||
restore_addons: list[str] | None,
|
restore_addons: list[str] | None,
|
||||||
@ -437,13 +439,13 @@ class SupervisorBackupReaderWriter(BackupReaderWriter):
|
|||||||
restore_complete = asyncio.Event()
|
restore_complete = asyncio.Event()
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def on_progress(data: Mapping[str, Any]) -> None:
|
def on_job_progress(data: Mapping[str, Any]) -> None:
|
||||||
"""Handle backup progress."""
|
"""Handle backup progress."""
|
||||||
if data.get("done") is True:
|
if data.get("done") is True:
|
||||||
restore_complete.set()
|
restore_complete.set()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
unsub = self._async_listen_job_events(job.job_id, on_progress)
|
unsub = self._async_listen_job_events(job.job_id, on_job_progress)
|
||||||
await restore_complete.wait()
|
await restore_complete.wait()
|
||||||
finally:
|
finally:
|
||||||
unsub()
|
unsub()
|
||||||
|
@ -2302,6 +2302,15 @@ async def test_restore_backup(
|
|||||||
"state": RestoreBackupState.IN_PROGRESS,
|
"state": RestoreBackupState.IN_PROGRESS,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result = await ws_client.receive_json()
|
||||||
|
assert result["event"] == {
|
||||||
|
"manager_state": BackupManagerState.RESTORE_BACKUP,
|
||||||
|
"stage": None,
|
||||||
|
"state": RestoreBackupState.CORE_RESTART,
|
||||||
|
}
|
||||||
|
|
||||||
|
# Note: The core restart is not tested here, in reality the following events
|
||||||
|
# are not sent because the core restart closes the WS connection.
|
||||||
result = await ws_client.receive_json()
|
result = await ws_client.receive_json()
|
||||||
assert result["event"] == {
|
assert result["event"] == {
|
||||||
"manager_state": BackupManagerState.RESTORE_BACKUP,
|
"manager_state": BackupManagerState.RESTORE_BACKUP,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user