mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-17 14:16:29 +00:00
Create backup of add-ons and core before update (#3369)
* Create backup of addons and core before update * Move responsibility
This commit is contained in:
parent
22238c9c0e
commit
e0fd31c390
@ -252,7 +252,7 @@ class AddonManager(CoreSysAttributes):
|
|||||||
],
|
],
|
||||||
on_condition=AddonsJobError,
|
on_condition=AddonsJobError,
|
||||||
)
|
)
|
||||||
async def update(self, slug: str) -> None:
|
async def update(self, slug: str, backup: Optional[bool] = False) -> None:
|
||||||
"""Update add-on."""
|
"""Update add-on."""
|
||||||
if slug not in self.local:
|
if slug not in self.local:
|
||||||
raise AddonsError(f"Add-on {slug} is not installed", _LOGGER.error)
|
raise AddonsError(f"Add-on {slug} is not installed", _LOGGER.error)
|
||||||
@ -273,6 +273,13 @@ class AddonManager(CoreSysAttributes):
|
|||||||
f"Add-on {slug} not supported on that platform", _LOGGER.error
|
f"Add-on {slug} not supported on that platform", _LOGGER.error
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if backup:
|
||||||
|
await self.sys_backups.do_backup_partial(
|
||||||
|
name=f"addon_{addon.slug}_{addon.version}",
|
||||||
|
homeassistant=False,
|
||||||
|
addons=[addon.slug],
|
||||||
|
)
|
||||||
|
|
||||||
# Update instance
|
# Update instance
|
||||||
last_state: AddonState = addon.state
|
last_state: AddonState = addon.state
|
||||||
old_image = addon.image
|
old_image = addon.image
|
||||||
|
@ -622,9 +622,9 @@ class AddonModel(CoreSysAttributes, ABC):
|
|||||||
"""Uninstall this add-on."""
|
"""Uninstall this add-on."""
|
||||||
return self.sys_addons.uninstall(self.slug)
|
return self.sys_addons.uninstall(self.slug)
|
||||||
|
|
||||||
def update(self) -> Awaitable[None]:
|
def update(self, backup: Optional[bool] = False) -> Awaitable[None]:
|
||||||
"""Update this add-on."""
|
"""Update this add-on."""
|
||||||
return self.sys_addons.update(self.slug)
|
return self.sys_addons.update(self.slug, backup=backup)
|
||||||
|
|
||||||
def rebuild(self) -> Awaitable[None]:
|
def rebuild(self) -> Awaitable[None]:
|
||||||
"""Rebuild this add-on."""
|
"""Rebuild this add-on."""
|
||||||
|
@ -10,6 +10,7 @@ from ..const import (
|
|||||||
ATTR_ARCH,
|
ATTR_ARCH,
|
||||||
ATTR_AUDIO_INPUT,
|
ATTR_AUDIO_INPUT,
|
||||||
ATTR_AUDIO_OUTPUT,
|
ATTR_AUDIO_OUTPUT,
|
||||||
|
ATTR_BACKUP,
|
||||||
ATTR_BLK_READ,
|
ATTR_BLK_READ,
|
||||||
ATTR_BLK_WRITE,
|
ATTR_BLK_WRITE,
|
||||||
ATTR_BOOT,
|
ATTR_BOOT,
|
||||||
@ -54,7 +55,12 @@ SCHEMA_OPTIONS = vol.Schema(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
SCHEMA_VERSION = vol.Schema({vol.Optional(ATTR_VERSION): version_tag})
|
SCHEMA_UPDATE = vol.Schema(
|
||||||
|
{
|
||||||
|
vol.Optional(ATTR_VERSION): version_tag,
|
||||||
|
vol.Optional(ATTR_BACKUP): bool,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class APIHomeAssistant(CoreSysAttributes):
|
class APIHomeAssistant(CoreSysAttributes):
|
||||||
@ -137,10 +143,14 @@ class APIHomeAssistant(CoreSysAttributes):
|
|||||||
@api_process
|
@api_process
|
||||||
async def update(self, request: web.Request) -> None:
|
async def update(self, request: web.Request) -> None:
|
||||||
"""Update Home Assistant."""
|
"""Update Home Assistant."""
|
||||||
body = await api_validate(SCHEMA_VERSION, request)
|
body = await api_validate(SCHEMA_UPDATE, request)
|
||||||
version = body.get(ATTR_VERSION, self.sys_homeassistant.latest_version)
|
|
||||||
|
|
||||||
await asyncio.shield(self.sys_homeassistant.core.update(version))
|
await asyncio.shield(
|
||||||
|
self.sys_homeassistant.core.update(
|
||||||
|
version=body.get(ATTR_VERSION, self.sys_homeassistant.latest_version),
|
||||||
|
backup=body.get(ATTR_BACKUP),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
@api_process
|
@api_process
|
||||||
def stop(self, request: web.Request) -> Awaitable[None]:
|
def stop(self, request: web.Request) -> Awaitable[None]:
|
||||||
|
@ -3,13 +3,15 @@ import asyncio
|
|||||||
from typing import Any, Awaitable
|
from typing import Any, Awaitable
|
||||||
|
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
from ..addons import AnyAddon
|
from ..addons import AnyAddon
|
||||||
from ..api.utils import api_process
|
from ..api.utils import api_process, api_validate
|
||||||
from ..const import (
|
from ..const import (
|
||||||
ATTR_ADDONS,
|
ATTR_ADDONS,
|
||||||
ATTR_ADVANCED,
|
ATTR_ADVANCED,
|
||||||
ATTR_AVAILABLE,
|
ATTR_AVAILABLE,
|
||||||
|
ATTR_BACKUP,
|
||||||
ATTR_BUILD,
|
ATTR_BUILD,
|
||||||
ATTR_DESCRIPTON,
|
ATTR_DESCRIPTON,
|
||||||
ATTR_HOMEASSISTANT,
|
ATTR_HOMEASSISTANT,
|
||||||
@ -34,6 +36,12 @@ from ..exceptions import APIError, APIForbidden
|
|||||||
from ..store.addon import AddonStore
|
from ..store.addon import AddonStore
|
||||||
from ..store.repository import Repository
|
from ..store.repository import Repository
|
||||||
|
|
||||||
|
SCHEMA_UPDATE = vol.Schema(
|
||||||
|
{
|
||||||
|
vol.Optional(ATTR_BACKUP): bool,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class APIStore(CoreSysAttributes):
|
class APIStore(CoreSysAttributes):
|
||||||
"""Handle RESTful API for store functions."""
|
"""Handle RESTful API for store functions."""
|
||||||
@ -134,12 +142,15 @@ class APIStore(CoreSysAttributes):
|
|||||||
return asyncio.shield(addon.install())
|
return asyncio.shield(addon.install())
|
||||||
|
|
||||||
@api_process
|
@api_process
|
||||||
def addons_addon_update(self, request: web.Request) -> Awaitable[None]:
|
async def addons_addon_update(self, request: web.Request) -> None:
|
||||||
"""Update add-on."""
|
"""Update add-on."""
|
||||||
addon = self._extract_addon(request, installed=True)
|
addon = self._extract_addon(request, installed=True)
|
||||||
if addon == request.get(REQUEST_FROM):
|
if addon == request.get(REQUEST_FROM):
|
||||||
raise APIForbidden(f"Add-on {addon.slug} can't update itself!")
|
raise APIForbidden(f"Add-on {addon.slug} can't update itself!")
|
||||||
return asyncio.shield(addon.update())
|
|
||||||
|
body = await api_validate(SCHEMA_UPDATE, request)
|
||||||
|
|
||||||
|
return await asyncio.shield(addon.update(backup=body.get(ATTR_BACKUP)))
|
||||||
|
|
||||||
@api_process
|
@api_process
|
||||||
async def addons_addon_info(self, request: web.Request) -> dict[str, Any]:
|
async def addons_addon_info(self, request: web.Request) -> dict[str, Any]:
|
||||||
|
@ -114,6 +114,7 @@ ATTR_AUTH = "auth"
|
|||||||
ATTR_AUTH_API = "auth_api"
|
ATTR_AUTH_API = "auth_api"
|
||||||
ATTR_AUTO_UPDATE = "auto_update"
|
ATTR_AUTO_UPDATE = "auto_update"
|
||||||
ATTR_AVAILABLE = "available"
|
ATTR_AVAILABLE = "available"
|
||||||
|
ATTR_BACKUP = "backup"
|
||||||
ATTR_BACKUP_EXCLUDE = "backup_exclude"
|
ATTR_BACKUP_EXCLUDE = "backup_exclude"
|
||||||
ATTR_BACKUP_POST = "backup_post"
|
ATTR_BACKUP_POST = "backup_post"
|
||||||
ATTR_BACKUP_PRE = "backup_pre"
|
ATTR_BACKUP_PRE = "backup_pre"
|
||||||
|
@ -12,6 +12,8 @@ from typing import Awaitable, Optional
|
|||||||
import attr
|
import attr
|
||||||
from awesomeversion import AwesomeVersion, AwesomeVersionException
|
from awesomeversion import AwesomeVersion, AwesomeVersionException
|
||||||
|
|
||||||
|
from supervisor.const import ATTR_HOMEASSISTANT
|
||||||
|
|
||||||
from ..coresys import CoreSys, CoreSysAttributes
|
from ..coresys import CoreSys, CoreSysAttributes
|
||||||
from ..docker.homeassistant import DockerHomeAssistant
|
from ..docker.homeassistant import DockerHomeAssistant
|
||||||
from ..docker.stats import DockerStats
|
from ..docker.stats import DockerStats
|
||||||
@ -173,7 +175,11 @@ class HomeAssistantCore(CoreSysAttributes):
|
|||||||
],
|
],
|
||||||
on_condition=HomeAssistantJobError,
|
on_condition=HomeAssistantJobError,
|
||||||
)
|
)
|
||||||
async def update(self, version: Optional[AwesomeVersion] = None) -> None:
|
async def update(
|
||||||
|
self,
|
||||||
|
version: Optional[AwesomeVersion] = None,
|
||||||
|
backup: Optional[bool] = False,
|
||||||
|
) -> None:
|
||||||
"""Update HomeAssistant version."""
|
"""Update HomeAssistant version."""
|
||||||
version = version or self.sys_homeassistant.latest_version
|
version = version or self.sys_homeassistant.latest_version
|
||||||
old_image = self.sys_homeassistant.image
|
old_image = self.sys_homeassistant.image
|
||||||
@ -186,6 +192,13 @@ class HomeAssistantCore(CoreSysAttributes):
|
|||||||
f"Version {version!s} is already installed", _LOGGER.warning
|
f"Version {version!s} is already installed", _LOGGER.warning
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if backup:
|
||||||
|
await self.sys_backups.do_backup_partial(
|
||||||
|
name=f"core_{self.instance.version}",
|
||||||
|
homeassistant=True,
|
||||||
|
folders=[ATTR_HOMEASSISTANT],
|
||||||
|
)
|
||||||
|
|
||||||
# process an update
|
# process an update
|
||||||
async def _update(to_version: AwesomeVersion) -> None:
|
async def _update(to_version: AwesomeVersion) -> None:
|
||||||
"""Run Home Assistant update."""
|
"""Run Home Assistant update."""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user