mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-04-19 10:47:15 +00:00
Check if backup is still available when accessing
When accessing a backup (e.g. to restore, download or delete it) check if the locations of the backup file are still available. If not, force a backup reload instead.
This commit is contained in:
parent
f02d67ee47
commit
b68d381c22
@ -143,11 +143,29 @@ SCHEMA_REMOVE = vol.Schema(
|
||||
class APIBackups(CoreSysAttributes):
|
||||
"""Handle RESTful API for backups functions."""
|
||||
|
||||
def _extract_slug(self, request):
|
||||
async def _get_backup_by_slug(self, request):
|
||||
"""Return backup, throw an exception if it doesn't exist."""
|
||||
backup = self.sys_backups.get(request.match_info.get("slug"))
|
||||
if not backup:
|
||||
raise APINotFound("Backup does not exist")
|
||||
|
||||
# Reload in case locations of this backup are no longer in sync
|
||||
# This usually means the user
|
||||
def _check_need_reload():
|
||||
for location in backup.all_locations:
|
||||
if not Path(location).exists():
|
||||
return False
|
||||
return True
|
||||
|
||||
if not await self.sys_run_in_executor(_check_need_reload):
|
||||
_LOGGER.warning(
|
||||
"Backup %s missing in at least one location, scheduling reload",
|
||||
backup.slug,
|
||||
)
|
||||
# Schedule a reload
|
||||
self.sys_jobs.schedule_job(self.sys_backups.reload, JobSchedulerOptions())
|
||||
raise APINotFound("Backup does not exist")
|
||||
|
||||
return backup
|
||||
|
||||
def _list_backups(self):
|
||||
@ -212,7 +230,7 @@ class APIBackups(CoreSysAttributes):
|
||||
@api_process
|
||||
async def backup_info(self, request):
|
||||
"""Return backup info."""
|
||||
backup = self._extract_slug(request)
|
||||
backup = await self._get_backup_by_slug(request)
|
||||
|
||||
data_addons = []
|
||||
for addon_data in backup.addons:
|
||||
@ -384,7 +402,7 @@ class APIBackups(CoreSysAttributes):
|
||||
@api_process
|
||||
async def restore_full(self, request: web.Request):
|
||||
"""Full restore of a backup."""
|
||||
backup = self._extract_slug(request)
|
||||
backup = await self._get_backup_by_slug(request)
|
||||
body = await api_validate(SCHEMA_RESTORE_FULL, request)
|
||||
self._validate_cloud_backup_location(
|
||||
request, body.get(ATTR_LOCATION, backup.location)
|
||||
@ -404,7 +422,7 @@ class APIBackups(CoreSysAttributes):
|
||||
@api_process
|
||||
async def restore_partial(self, request: web.Request):
|
||||
"""Partial restore a backup."""
|
||||
backup = self._extract_slug(request)
|
||||
backup = await self._get_backup_by_slug(request)
|
||||
body = await api_validate(SCHEMA_RESTORE_PARTIAL, request)
|
||||
self._validate_cloud_backup_location(
|
||||
request, body.get(ATTR_LOCATION, backup.location)
|
||||
@ -435,7 +453,7 @@ class APIBackups(CoreSysAttributes):
|
||||
@api_process
|
||||
async def remove(self, request: web.Request):
|
||||
"""Remove a backup."""
|
||||
backup = self._extract_slug(request)
|
||||
backup = await self._get_backup_by_slug(request)
|
||||
body = await api_validate(SCHEMA_REMOVE, request)
|
||||
locations: list[LOCATION_TYPE] | None = None
|
||||
|
||||
@ -450,7 +468,7 @@ class APIBackups(CoreSysAttributes):
|
||||
@api_process
|
||||
async def download(self, request: web.Request):
|
||||
"""Download a backup file."""
|
||||
backup = self._extract_slug(request)
|
||||
backup = self._get_backup_by_slug(request)
|
||||
# Query will give us '' for /backups, convert value to None
|
||||
location = request.query.get(ATTR_LOCATION, backup.location) or None
|
||||
self._validate_cloud_backup_location(request, location)
|
||||
|
@ -200,18 +200,19 @@ class BackupManager(FileConfiguration, JobGroup):
|
||||
return backup
|
||||
|
||||
def load(self) -> Awaitable[None]:
|
||||
"""Load exists backups data.
|
||||
"""Load existing backups data.
|
||||
|
||||
Return a coroutine.
|
||||
"""
|
||||
return self.reload()
|
||||
|
||||
@Job(name="backup_reload")
|
||||
async def reload(
|
||||
self,
|
||||
location: LOCATION_TYPE | type[DEFAULT] = DEFAULT,
|
||||
filename: str | None = None,
|
||||
) -> bool:
|
||||
"""Load exists backups."""
|
||||
"""Load existing backups."""
|
||||
|
||||
async def _load_backup(location: str | None, tar_file: Path) -> bool:
|
||||
"""Load the backup."""
|
||||
|
Loading…
x
Reference in New Issue
Block a user