From e41592355305c96ea94ae05bb283a5b80d7153f7 Mon Sep 17 00:00:00 2001 From: ludeeus Date: Wed, 16 Oct 2024 04:54:29 +0000 Subject: [PATCH] Trigger backup sync when backup is complete --- supervisor/backups/manager.py | 17 ++++++++++++++ supervisor/homeassistant/const.py | 1 + supervisor/homeassistant/websocket.py | 1 + tests/backups/test_manager.py | 34 +++++++++++++++++++++++++++ 4 files changed, 53 insertions(+) diff --git a/supervisor/backups/manager.py b/supervisor/backups/manager.py index 0bdcea6f5..3ef8ebb30 100644 --- a/supervisor/backups/manager.py +++ b/supervisor/backups/manager.py @@ -10,7 +10,10 @@ from pathlib import Path from ..addons.addon import Addon from ..const import ( + ATTR_DATA, ATTR_DAYS_UNTIL_STALE, + ATTR_SLUG, + ATTR_TYPE, FILE_HASSIO_BACKUPS, FOLDER_HOMEASSISTANT, CoreState, @@ -21,7 +24,9 @@ from ..exceptions import ( BackupInvalidError, BackupJobError, BackupMountDownError, + HomeAssistantWSError, ) +from ..homeassistant.const import WSType from ..jobs.const import JOB_GROUP_BACKUP_MANAGER, JobCondition, JobExecutionLimit from ..jobs.decorator import Job from ..jobs.job_group import JobGroup @@ -299,6 +304,18 @@ class BackupManager(FileConfiguration, JobGroup): # Ignore exceptions from waiting for addon startup, addon errors handled elsewhere await asyncio.gather(*addon_start_tasks, return_exceptions=True) + try: + await self.sys_homeassistant.websocket.async_send_command( + { + ATTR_TYPE: WSType.BACKUP_SYNC, + ATTR_DATA: { + ATTR_SLUG: backup.slug, + }, + }, + ) + except HomeAssistantWSError as err: + _LOGGER.error("Can't send backup sync to Home Assistant: %s", err) + return backup finally: self.sys_core.state = CoreState.RUNNING diff --git a/supervisor/homeassistant/const.py b/supervisor/homeassistant/const.py index 192433547..246cd5235 100644 --- a/supervisor/homeassistant/const.py +++ b/supervisor/homeassistant/const.py @@ -32,6 +32,7 @@ class WSType(StrEnum): SUPERVISOR_EVENT = "supervisor/event" BACKUP_START = "backup/start" BACKUP_END = "backup/end" + BACKUP_SYNC = "backup/sync" class WSEvent(StrEnum): diff --git a/supervisor/homeassistant/websocket.py b/supervisor/homeassistant/websocket.py index 2c54eda64..d6573fa44 100644 --- a/supervisor/homeassistant/websocket.py +++ b/supervisor/homeassistant/websocket.py @@ -34,6 +34,7 @@ MIN_VERSION = { WSType.SUPERVISOR_EVENT: "2021.2.4", WSType.BACKUP_START: "2022.1.0", WSType.BACKUP_END: "2022.1.0", + WSType.BACKUP_SYNC: "2024.10.99", } _LOGGER: logging.Logger = logging.getLogger(__name__) diff --git a/tests/backups/test_manager.py b/tests/backups/test_manager.py index 9037e7765..0a2904ea5 100644 --- a/tests/backups/test_manager.py +++ b/tests/backups/test_manager.py @@ -1169,6 +1169,40 @@ async def test_backup_progress( ] +async def test_backup_sync_notification( + coresys: CoreSys, + install_addon_ssh: Addon, + container: MagicMock, + ha_ws_client: AsyncMock, + tmp_supervisor_data, + path_extern, +): + """Test backup sync notification.""" + container.status = "running" + install_addon_ssh.path_data.mkdir() + coresys.core.state = CoreState.RUNNING + ha_ws_client.ha_version = AwesomeVersion("9999.9.9") + coresys.hardware.disk.get_disk_free_space = lambda x: 5000 + + ha_ws_client.async_send_command.reset_mock() + partial_backup: Backup = await coresys.backups.do_backup_partial() + await asyncio.sleep(0) + + messages = [ + call.args[0] + for call in ha_ws_client.async_send_command.call_args_list + if call.args[0]["type"] == WSType.BACKUP_SYNC + ] + assert messages == [ + { + "data": { + "slug": partial_backup.slug, + }, + "type": WSType.BACKUP_SYNC, + }, + ] + + async def test_restore_progress( request: pytest.FixtureRequest, coresys: CoreSys,