mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-19 15:16:33 +00:00
Offload rauc logic with partition handling (#1404)
* Offload rauc logic with partition handling * Fix name * Fix detection * Add to API
This commit is contained in:
parent
a0d106529c
commit
5365aa4466
46
API.md
46
API.md
@ -18,7 +18,7 @@ On success / Code 200:
|
||||
```json
|
||||
{
|
||||
"result": "ok",
|
||||
"data": { }
|
||||
"data": {}
|
||||
}
|
||||
```
|
||||
|
||||
@ -56,12 +56,10 @@ The addons from `addons` are only installed one.
|
||||
"installed": "INSTALL_VERSION",
|
||||
"icon": "bool",
|
||||
"logo": "bool",
|
||||
"state": "started|stopped",
|
||||
"state": "started|stopped"
|
||||
}
|
||||
],
|
||||
"addons_repositories": [
|
||||
"REPO_URL"
|
||||
]
|
||||
"addons_repositories": ["REPO_URL"]
|
||||
}
|
||||
```
|
||||
|
||||
@ -85,9 +83,7 @@ Optional:
|
||||
"debug": "bool",
|
||||
"debug_block": "bool",
|
||||
"logging": "debug|info|warning|error|critical",
|
||||
"addons_repositories": [
|
||||
"REPO_URL"
|
||||
]
|
||||
"addons_repositories": ["REPO_URL"]
|
||||
}
|
||||
```
|
||||
|
||||
@ -100,6 +96,7 @@ Reload addons/version.
|
||||
Output is the raw docker log.
|
||||
|
||||
- GET `/supervisor/stats`
|
||||
|
||||
```json
|
||||
{
|
||||
"cpu_percent": 0.0,
|
||||
@ -140,6 +137,7 @@ Repair overlayfs issue and restore lost images
|
||||
- POST `/snapshots/new/upload`
|
||||
|
||||
return:
|
||||
|
||||
```json
|
||||
{
|
||||
"slug": ""
|
||||
@ -156,6 +154,7 @@ return:
|
||||
```
|
||||
|
||||
return:
|
||||
|
||||
```json
|
||||
{
|
||||
"slug": ""
|
||||
@ -174,6 +173,7 @@ return:
|
||||
```
|
||||
|
||||
return:
|
||||
|
||||
```json
|
||||
{
|
||||
"slug": ""
|
||||
@ -247,7 +247,7 @@ return:
|
||||
"kernel": "4.15.7|null",
|
||||
"chassis": "specific|null",
|
||||
"deployment": "stable|beta|dev|null",
|
||||
"cpe": "xy|null",
|
||||
"cpe": "xy|null"
|
||||
}
|
||||
```
|
||||
|
||||
@ -255,7 +255,7 @@ return:
|
||||
|
||||
```json
|
||||
{
|
||||
"hostname": "",
|
||||
"hostname": ""
|
||||
}
|
||||
```
|
||||
|
||||
@ -264,6 +264,7 @@ return:
|
||||
#### Services
|
||||
|
||||
- GET `/host/services`
|
||||
|
||||
```json
|
||||
{
|
||||
"services": [
|
||||
@ -285,17 +286,20 @@ return:
|
||||
### HassOS
|
||||
|
||||
- GET `/hassos/info`
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "2.3",
|
||||
"version_cli": "7",
|
||||
"version_latest": "2.4",
|
||||
"version_cli_latest": "8",
|
||||
"board": "ova|rpi"
|
||||
"board": "ova|rpi",
|
||||
"boot": "rauc boot slot"
|
||||
}
|
||||
```
|
||||
|
||||
- POST `/hassos/update`
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "optional"
|
||||
@ -303,6 +307,7 @@ return:
|
||||
```
|
||||
|
||||
- POST `/hassos/update/cli`
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "optional"
|
||||
@ -316,6 +321,7 @@ Load host configs from a USB stick.
|
||||
### Hardware
|
||||
|
||||
- GET `/hardware/info`
|
||||
|
||||
```json
|
||||
{
|
||||
"serial": ["/dev/xy"],
|
||||
@ -336,6 +342,7 @@ Load host configs from a USB stick.
|
||||
```
|
||||
|
||||
- GET `/hardware/audio`
|
||||
|
||||
```json
|
||||
{
|
||||
"audio": {
|
||||
@ -421,6 +428,7 @@ Proxy to real home-assistant instance.
|
||||
Proxy to real websocket instance.
|
||||
|
||||
- GET `/homeassistant/stats`
|
||||
|
||||
```json
|
||||
{
|
||||
"cpu_percent": 0.0,
|
||||
@ -568,7 +576,7 @@ This function is not callable by itself.
|
||||
|
||||
```json
|
||||
{
|
||||
"protected": "bool",
|
||||
"protected": "bool"
|
||||
}
|
||||
```
|
||||
|
||||
@ -597,6 +605,7 @@ Only supported for local build addons
|
||||
Write data to add-on stdin
|
||||
|
||||
- GET `/addons/{addon}/stats`
|
||||
|
||||
```json
|
||||
{
|
||||
"cpu_percent": 0.0,
|
||||
@ -647,6 +656,7 @@ Need ingress session as cookie.
|
||||
### discovery
|
||||
|
||||
- GET `/discovery`
|
||||
|
||||
```json
|
||||
{
|
||||
"discovery": [
|
||||
@ -661,6 +671,7 @@ Need ingress session as cookie.
|
||||
```
|
||||
|
||||
- GET `/discovery/{UUID}`
|
||||
|
||||
```json
|
||||
{
|
||||
"addon": "slug",
|
||||
@ -671,6 +682,7 @@ Need ingress session as cookie.
|
||||
```
|
||||
|
||||
- POST `/discovery`
|
||||
|
||||
```json
|
||||
{
|
||||
"service": "name",
|
||||
@ -679,6 +691,7 @@ Need ingress session as cookie.
|
||||
```
|
||||
|
||||
return:
|
||||
|
||||
```json
|
||||
{
|
||||
"uuid": "uuid"
|
||||
@ -690,6 +703,7 @@ return:
|
||||
### Services
|
||||
|
||||
- GET `/services`
|
||||
|
||||
```json
|
||||
{
|
||||
"services": [
|
||||
@ -705,6 +719,7 @@ return:
|
||||
#### MQTT
|
||||
|
||||
- GET `/services/mqtt`
|
||||
|
||||
```json
|
||||
{
|
||||
"addon": "name",
|
||||
@ -718,6 +733,7 @@ return:
|
||||
```
|
||||
|
||||
- POST `/services/mqtt`
|
||||
|
||||
```json
|
||||
{
|
||||
"host": "xy",
|
||||
@ -734,6 +750,7 @@ return:
|
||||
### Misc
|
||||
|
||||
- GET `/info`
|
||||
|
||||
```json
|
||||
{
|
||||
"supervisor": "version",
|
||||
@ -752,6 +769,7 @@ return:
|
||||
### DNS
|
||||
|
||||
- GET `/dns/info`
|
||||
|
||||
```json
|
||||
{
|
||||
"host": "ip-address",
|
||||
@ -763,6 +781,7 @@ return:
|
||||
```
|
||||
|
||||
- POST `/dns/options`
|
||||
|
||||
```json
|
||||
{
|
||||
"servers": ["dns://8.8.8.8"]
|
||||
@ -770,6 +789,7 @@ return:
|
||||
```
|
||||
|
||||
- POST `/dns/update`
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "VERSION"
|
||||
@ -781,6 +801,7 @@ return:
|
||||
- GET `/dns/logs`
|
||||
|
||||
- GET `/dns/stats`
|
||||
|
||||
```json
|
||||
{
|
||||
"cpu_percent": 0.0,
|
||||
@ -802,6 +823,7 @@ supervisor.
|
||||
You can call post `/auth`
|
||||
|
||||
We support:
|
||||
|
||||
- Json `{ "user|name": "...", "password": "..." }`
|
||||
- application/x-www-form-urlencoded `user|name=...&password=...`
|
||||
- BasicAuth
|
||||
|
@ -3,11 +3,12 @@ import asyncio
|
||||
import logging
|
||||
from typing import Any, Awaitable, Dict
|
||||
|
||||
import voluptuous as vol
|
||||
from aiohttp import web
|
||||
import voluptuous as vol
|
||||
|
||||
from ..const import (
|
||||
ATTR_BOARD,
|
||||
ATTR_BOOT,
|
||||
ATTR_VERSION,
|
||||
ATTR_VERSION_CLI,
|
||||
ATTR_VERSION_CLI_LATEST,
|
||||
@ -33,6 +34,7 @@ class APIHassOS(CoreSysAttributes):
|
||||
ATTR_VERSION_LATEST: self.sys_hassos.version_latest,
|
||||
ATTR_VERSION_CLI_LATEST: self.sys_hassos.version_cli_latest,
|
||||
ATTR_BOARD: self.sys_hassos.board,
|
||||
ATTR_BOOT: self.sys_dbus.rauc.boot_slot,
|
||||
}
|
||||
|
||||
@api_process
|
||||
|
@ -79,7 +79,11 @@ class HassIO(CoreSysAttributes):
|
||||
"""Start Hass.io orchestration."""
|
||||
await self.sys_api.start()
|
||||
|
||||
# on release channel, try update itself
|
||||
# Mark booted partition as healthy
|
||||
if self.sys_hassos.available:
|
||||
await self.sys_hassos.mark_healthy()
|
||||
|
||||
# On release channel, try update itself
|
||||
if self.sys_supervisor.need_update:
|
||||
try:
|
||||
if self.sys_dev:
|
||||
@ -92,7 +96,7 @@ class HassIO(CoreSysAttributes):
|
||||
"future version of Home Assistant!"
|
||||
)
|
||||
|
||||
# start addon mark as initialize
|
||||
# Start addon mark as initialize
|
||||
await self.sys_addons.boot(STARTUP_INITIALIZE)
|
||||
|
||||
try:
|
||||
|
@ -1,6 +1,7 @@
|
||||
"""D-Bus interface for rauc."""
|
||||
import logging
|
||||
from typing import Optional
|
||||
from enum import Enum
|
||||
|
||||
from .interface import DBusInterface
|
||||
from .utils import dbus_connected
|
||||
@ -13,6 +14,14 @@ DBUS_NAME = "de.pengutronix.rauc"
|
||||
DBUS_OBJECT = "/"
|
||||
|
||||
|
||||
class RaucState(str, Enum):
|
||||
"""Rauc slot states."""
|
||||
|
||||
GOOD = "good"
|
||||
BAD = "bad"
|
||||
ACTIVE = "active"
|
||||
|
||||
|
||||
class Rauc(DBusInterface):
|
||||
"""Handle D-Bus interface for rauc."""
|
||||
|
||||
@ -82,6 +91,14 @@ class Rauc(DBusInterface):
|
||||
"""
|
||||
return self.dbus.wait_signal(f"{DBUS_NAME}.Installer.Completed")
|
||||
|
||||
@dbus_connected
|
||||
def mark(self, state: RaucState, slot_identifier: str):
|
||||
"""Get slot status.
|
||||
|
||||
Return a coroutine.
|
||||
"""
|
||||
return self.dbus.Installer.Mark(state, slot_identifier)
|
||||
|
||||
@dbus_connected
|
||||
async def update(self):
|
||||
"""Update Properties."""
|
||||
|
@ -427,9 +427,10 @@ class DockerInterface(CoreSysAttributes):
|
||||
continue
|
||||
available_version.append(version)
|
||||
|
||||
assert available_version
|
||||
if not available_version:
|
||||
raise ValueError()
|
||||
|
||||
except (docker.errors.DockerException, AssertionError):
|
||||
except (docker.errors.DockerException, ValueError):
|
||||
_LOGGER.debug("No version found for %s", self.image)
|
||||
raise DockerAPIError()
|
||||
else:
|
||||
|
@ -17,6 +17,7 @@ from .exceptions import (
|
||||
HassOSUpdateError,
|
||||
DockerAPIError,
|
||||
)
|
||||
from .dbus.rauc import RaucState
|
||||
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
@ -111,20 +112,19 @@ class HassOS(CoreSysAttributes):
|
||||
async def load(self) -> None:
|
||||
"""Load HassOS data."""
|
||||
try:
|
||||
# Check needed host functions
|
||||
assert self.sys_dbus.rauc.is_connected
|
||||
assert self.sys_dbus.systemd.is_connected
|
||||
assert self.sys_dbus.hostname.is_connected
|
||||
|
||||
assert self.sys_host.info.cpe is not None
|
||||
if self.sys_host.info.cpe is None:
|
||||
raise TypeError()
|
||||
cpe = CPE(self.sys_host.info.cpe)
|
||||
assert cpe.get_product()[0] == "hassos"
|
||||
except (AssertionError, NotImplementedError):
|
||||
|
||||
if cpe.get_product()[0] != "hassos":
|
||||
raise TypeError()
|
||||
except TypeError:
|
||||
_LOGGER.debug("Found no HassOS")
|
||||
return
|
||||
else:
|
||||
self._available = True
|
||||
|
||||
# Store meta data
|
||||
self._available = True
|
||||
self._version = cpe.get_version()[0]
|
||||
self._board = cpe.get_target_hardware()[0]
|
||||
|
||||
@ -210,3 +210,12 @@ class HassOS(CoreSysAttributes):
|
||||
await self.instance.install(self.version_cli, latest=True)
|
||||
except DockerAPIError:
|
||||
_LOGGER.error("Repairing of HassOS CLI fails")
|
||||
|
||||
async def mark_healthy(self):
|
||||
"""Set booted partition as good for rauc."""
|
||||
try:
|
||||
response = await self.sys_dbus.rauc.mark(RaucState.GOOD, "booted")
|
||||
except DBusError:
|
||||
_LOGGER.error("Can't mark booted partition as healty!")
|
||||
else:
|
||||
_LOGGER.info("Rauc: %s - %s", self.sys_dbus.rauc.boot_slot, response[1])
|
||||
|
@ -124,9 +124,10 @@ def secure_path(tar: tarfile.TarFile) -> Generator[tarfile.TarInfo, None, None]:
|
||||
for member in tar:
|
||||
file_path = Path(member.name)
|
||||
try:
|
||||
assert not file_path.is_absolute()
|
||||
if file_path.is_absolute():
|
||||
raise ValueError()
|
||||
Path("/fake", file_path).resolve().relative_to("/fake")
|
||||
except (ValueError, RuntimeError, AssertionError):
|
||||
except (ValueError, RuntimeError):
|
||||
_LOGGER.warning("Issue with file %s", file_path)
|
||||
continue
|
||||
else:
|
||||
|
Loading…
x
Reference in New Issue
Block a user