Proper handling of unavailable Synology DSM nas during backup (#140721)

* raise BackupAgentUnreachableError when NAS is unavailable

* also raise BackupAgentUnreachableError during upload when nas unavailable

* Revert "also raise BackupAgentUnreachableError during upload when nas unavailable"

This reverts commit 38877d8540aa3c61c366069dc063bb9b4d866c48.

* Revert "raise BackupAgentUnreachableError when NAS is unavailable"

This reverts commit 4d8cfae396ea3be3409ed8f4784b9e2448954a04.

* check last_update_success of  coordinator_central to get backup agents

* consider last_update_success before notify backup listeners

* add test

* use walrus :=  :)
This commit is contained in:
Michael 2025-03-26 10:22:43 +01:00 committed by GitHub
parent f0c774a4bd
commit b5117eb071
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 63 additions and 1 deletions

View File

@ -123,6 +123,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: SynologyDSMConfigEntry)
entry.runtime_data = SynologyDSMData(
api=api,
coordinator_central=coordinator_central,
coordinator_central_old_update_success=True,
coordinator_cameras=coordinator_cameras,
coordinator_switches=coordinator_switches,
)
@ -139,6 +140,17 @@ async def async_setup_entry(hass: HomeAssistant, entry: SynologyDSMConfigEntry)
entry.async_on_state_change(async_notify_backup_listeners)
)
def async_check_last_update_success() -> None:
if (
last := coordinator_central.last_update_success
) is not entry.runtime_data.coordinator_central_old_update_success:
entry.runtime_data.coordinator_central_old_update_success = last
async_notify_backup_listeners()
entry.runtime_data.coordinator_central.async_add_listener(
async_check_last_update_success
)
return True

View File

@ -58,6 +58,7 @@ async def async_get_backup_agents(
if entry.unique_id is not None
and entry.runtime_data.api.file_station
and entry.options.get(CONF_BACKUP_PATH)
and entry.runtime_data.coordinator_central.last_update_success
]

View File

@ -35,6 +35,7 @@ class SynologyDSMData:
api: SynoApi
coordinator_central: SynologyDSMCentralUpdateCoordinator
coordinator_central_old_update_success: bool
coordinator_cameras: SynologyDSMCameraUpdateCoordinator | None
coordinator_switches: SynologyDSMSwitchUpdateCoordinator | None

View File

@ -4,9 +4,13 @@ from io import StringIO
from typing import Any
from unittest.mock import ANY, AsyncMock, MagicMock, Mock, patch
from freezegun.api import FrozenDateTimeFactory
import pytest
from synology_dsm.api.file_station.models import SynoFileFile, SynoFileSharedFolder
from synology_dsm.exceptions import SynologyDSMAPIErrorException
from synology_dsm.exceptions import (
SynologyDSMAPIErrorException,
SynologyDSMRequestException,
)
from homeassistant.components.backup import (
DOMAIN as BACKUP_DOMAIN,
@ -279,6 +283,50 @@ async def test_agents_on_unload(
}
async def test_agents_on_changed_update_success(
hass: HomeAssistant,
setup_dsm_with_filestation: MagicMock,
hass_ws_client: WebSocketGenerator,
freezer: FrozenDateTimeFactory,
) -> None:
"""Test backup agent on changed update success of coordintaor."""
client = await hass_ws_client(hass)
# config entry is loaded
await client.send_json_auto_id({"type": "backup/agents/info"})
response = await client.receive_json()
assert response["success"]
assert len(response["result"]["agents"]) == 2
# coordinator update was successful
freezer.tick(910) # 15 min interval + 10s
await hass.async_block_till_done(wait_background_tasks=True)
await client.send_json_auto_id({"type": "backup/agents/info"})
response = await client.receive_json()
assert response["success"]
assert len(response["result"]["agents"]) == 2
# coordinator update was un-successful
setup_dsm_with_filestation.update.side_effect = SynologyDSMRequestException(
OSError()
)
freezer.tick(910)
await hass.async_block_till_done(wait_background_tasks=True)
await client.send_json_auto_id({"type": "backup/agents/info"})
response = await client.receive_json()
assert response["success"]
assert len(response["result"]["agents"]) == 1
# coordinator update was successful again
setup_dsm_with_filestation.update.side_effect = None
freezer.tick(910)
await hass.async_block_till_done(wait_background_tasks=True)
await client.send_json_auto_id({"type": "backup/agents/info"})
response = await client.receive_json()
assert response["success"]
assert len(response["result"]["agents"]) == 2
async def test_agents_list_backups(
hass: HomeAssistant,
setup_dsm_with_filestation: MagicMock,