mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-08-23 07:59:21 +00:00
Compare commits
12 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
4617de754f | ||
![]() |
fb8bc0b2b7 | ||
![]() |
3b8ae878b4 | ||
![]() |
39baea759a | ||
![]() |
80ddb1d262 | ||
![]() |
e24987a610 | ||
![]() |
9e5c276e3b | ||
![]() |
c33d31996d | ||
![]() |
aa1f08fe8a | ||
![]() |
d78689554a | ||
![]() |
5bee1d851c | ||
![]() |
ddb8eef4d1 |
53
API.md
53
API.md
@@ -1,6 +1,6 @@
|
|||||||
# Hass.io
|
# Supervisor
|
||||||
|
|
||||||
## Hass.io RESTful API
|
## Supervisor RESTful API
|
||||||
|
|
||||||
Interface for Home Assistant to control things from supervisor.
|
Interface for Home Assistant to control things from supervisor.
|
||||||
|
|
||||||
@@ -22,9 +22,10 @@ On success / Code 200:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
For access to API you need set the `X-HASSIO-KEY` they will be available for Add-ons/HomeAssistant with environment `HASSIO_TOKEN`.
|
For access to API you need use a authorization header with a `Bearer` token.
|
||||||
|
They are available for Add-ons and the Home Assistant using the `SUPERVISOR_TOKEN` environment variable.
|
||||||
|
|
||||||
### Hass.io
|
### Supervisor
|
||||||
|
|
||||||
- GET `/supervisor/ping`
|
- GET `/supervisor/ping`
|
||||||
|
|
||||||
@@ -285,7 +286,7 @@ return:
|
|||||||
|
|
||||||
### HassOS
|
### HassOS
|
||||||
|
|
||||||
- GET `/hassos/info`
|
- GET `/os/info`
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -298,7 +299,7 @@ return:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- POST `/hassos/update`
|
- POST `/os/update`
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -306,7 +307,7 @@ return:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- POST `/hassos/update/cli`
|
- POST `/os/update/cli`
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -314,7 +315,7 @@ return:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- POST `/hassos/config/sync`
|
- POST `/os/config/sync`
|
||||||
|
|
||||||
Load host configs from a USB stick.
|
Load host configs from a USB stick.
|
||||||
|
|
||||||
@@ -363,7 +364,7 @@ Trigger an udev reload
|
|||||||
|
|
||||||
### Home Assistant
|
### Home Assistant
|
||||||
|
|
||||||
- GET `/homeassistant/info`
|
- GET `/core/info`
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -382,7 +383,7 @@ Trigger an udev reload
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- POST `/homeassistant/update`
|
- POST `/core/update`
|
||||||
|
|
||||||
Optional:
|
Optional:
|
||||||
|
|
||||||
@@ -392,23 +393,23 @@ Optional:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- GET `/homeassistant/logs`
|
- GET `/core/logs`
|
||||||
|
|
||||||
Output is the raw Docker log.
|
Output is the raw Docker log.
|
||||||
|
|
||||||
- POST `/homeassistant/restart`
|
- POST `/core/restart`
|
||||||
- POST `/homeassistant/check`
|
- POST `/core/check`
|
||||||
- POST `/homeassistant/start`
|
- POST `/core/start`
|
||||||
- POST `/homeassistant/stop`
|
- POST `/core/stop`
|
||||||
- POST `/homeassistant/rebuild`
|
- POST `/core/rebuild`
|
||||||
|
|
||||||
- POST `/homeassistant/options`
|
- POST `/core/options`
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"image": "Optional|null",
|
"image": "Optional|null",
|
||||||
"last_version": "Optional for custom image|null",
|
"last_version": "Optional for custom image|null",
|
||||||
"port": "port for access hass",
|
"port": "port for access core",
|
||||||
"ssl": "bool",
|
"ssl": "bool",
|
||||||
"refresh_token": "",
|
"refresh_token": "",
|
||||||
"watchdog": "bool",
|
"watchdog": "bool",
|
||||||
@@ -418,15 +419,15 @@ Output is the raw Docker log.
|
|||||||
|
|
||||||
Image with `null` and last_version with `null` reset this options.
|
Image with `null` and last_version with `null` reset this options.
|
||||||
|
|
||||||
- POST/GET `/homeassistant/api`
|
- POST/GET `/core/api`
|
||||||
|
|
||||||
Proxy to real home-assistant instance.
|
Proxy to the Home Assistant Core instance.
|
||||||
|
|
||||||
- GET `/homeassistant/websocket`
|
- GET `/core/websocket`
|
||||||
|
|
||||||
Proxy to real websocket instance.
|
Proxy to Home Assistant Core websocket.
|
||||||
|
|
||||||
- GET `/homeassistant/stats`
|
- GET `/core/stats`
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -441,13 +442,13 @@ Proxy to real websocket instance.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### RESTful for API addons
|
### RESTful for API add-ons
|
||||||
|
|
||||||
If an add-on will call itself, you can use `/addons/self/...`.
|
If an add-on will call itself, you can use `/addons/self/...`.
|
||||||
|
|
||||||
- GET `/addons`
|
- GET `/addons`
|
||||||
|
|
||||||
Get all available addons.
|
Get all available add-ons.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -500,7 +501,7 @@ Get all available addons.
|
|||||||
"stage": "stable|experimental|deprecated",
|
"stage": "stable|experimental|deprecated",
|
||||||
"arch": ["armhf", "aarch64", "i386", "amd64"],
|
"arch": ["armhf", "aarch64", "i386", "amd64"],
|
||||||
"machine": "[raspberrypi2, tinker]",
|
"machine": "[raspberrypi2, tinker]",
|
||||||
"homeassistant": "null|min Home Assistant version",
|
"homeassistant": "null|min Home Assistant Core version",
|
||||||
"repository": "12345678|null",
|
"repository": "12345678|null",
|
||||||
"version": "null|VERSION_INSTALLED",
|
"version": "null|VERSION_INSTALLED",
|
||||||
"last_version": "LAST_VERSION",
|
"last_version": "LAST_VERSION",
|
||||||
|
@@ -10,10 +10,8 @@ trigger:
|
|||||||
- "*"
|
- "*"
|
||||||
pr: none
|
pr: none
|
||||||
variables:
|
variables:
|
||||||
- name: basePythonTag
|
|
||||||
value: "3.7-alpine3.11"
|
|
||||||
- name: versionBuilder
|
- name: versionBuilder
|
||||||
value: "6.9"
|
value: "7.0"
|
||||||
- group: docker
|
- group: docker
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -51,6 +49,5 @@ jobs:
|
|||||||
-v ~/.docker:/root/.docker \
|
-v ~/.docker:/root/.docker \
|
||||||
-v /run/docker.sock:/run/docker.sock:rw -v $(pwd):/data:ro \
|
-v /run/docker.sock:/run/docker.sock:rw -v $(pwd):/data:ro \
|
||||||
homeassistant/amd64-builder:$(versionBuilder) \
|
homeassistant/amd64-builder:$(versionBuilder) \
|
||||||
--supervisor $(basePythonTag) --version $(Build.SourceBranchName) \
|
--generic $(Build.SourceBranchName) --all -t /data
|
||||||
--all -t /data --docker-hub homeassistant
|
|
||||||
displayName: "Build Release"
|
displayName: "Build Release"
|
||||||
|
13
build.json
Normal file
13
build.json
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"image": "homeassistant/{arch}-hassio-supervisor",
|
||||||
|
"build_from": {
|
||||||
|
"aarch64": "homeassistant/aarch64-base-python:3.7-alpine3.11",
|
||||||
|
"armhf": "homeassistant/armhf-base-python:3.7-alpine3.11",
|
||||||
|
"armv7": "homeassistant/armv7-base-python:3.7-alpine3.11",
|
||||||
|
"amd64": "homeassistant/amd64-base-python:3.7-alpine3.11",
|
||||||
|
"i386": "homeassistant/i386-base-python:3.7-alpine3.11"
|
||||||
|
},
|
||||||
|
"labels": {
|
||||||
|
"io.hass.type": "supervisor"
|
||||||
|
}
|
||||||
|
}
|
@@ -272,11 +272,14 @@ class AddonManager(CoreSysAttributes):
|
|||||||
await addon.restore(tar_file)
|
await addon.restore(tar_file)
|
||||||
|
|
||||||
# Check if new
|
# Check if new
|
||||||
if slug in self.local:
|
if slug not in self.local:
|
||||||
return
|
_LOGGER.info("Detect new Add-on after restore %s", slug)
|
||||||
|
self.local[slug] = addon
|
||||||
|
|
||||||
_LOGGER.info("Detect new Add-on after restore %s", slug)
|
# Update ingress
|
||||||
self.local[slug] = addon
|
if addon.with_ingress:
|
||||||
|
with suppress(HomeAssistantAPIError):
|
||||||
|
await self.sys_ingress.update_hass_panel(addon)
|
||||||
|
|
||||||
async def repair(self) -> None:
|
async def repair(self) -> None:
|
||||||
"""Repair local add-ons."""
|
"""Repair local add-ons."""
|
||||||
|
@@ -3,7 +3,7 @@ from enum import Enum
|
|||||||
from ipaddress import ip_network
|
from ipaddress import ip_network
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
HASSIO_VERSION = "200"
|
HASSIO_VERSION = "206"
|
||||||
|
|
||||||
|
|
||||||
URL_HASSIO_ADDONS = "https://github.com/home-assistant/hassio-addons"
|
URL_HASSIO_ADDONS = "https://github.com/home-assistant/hassio-addons"
|
||||||
|
@@ -121,6 +121,8 @@ class HassIO(CoreSysAttributes):
|
|||||||
):
|
):
|
||||||
with suppress(HomeAssistantError):
|
with suppress(HomeAssistantError):
|
||||||
await self.sys_homeassistant.start()
|
await self.sys_homeassistant.start()
|
||||||
|
else:
|
||||||
|
_LOGGER.info("Skip start of Home Assistant")
|
||||||
|
|
||||||
# start addon mark as application
|
# start addon mark as application
|
||||||
await self.sys_addons.boot(STARTUP_APPLICATION)
|
await self.sys_addons.boot(STARTUP_APPLICATION)
|
||||||
|
@@ -113,11 +113,6 @@ class CoreDNS(JsonConfig, CoreSysAttributes):
|
|||||||
self.version = self.instance.version
|
self.version = self.instance.version
|
||||||
self.save_data()
|
self.save_data()
|
||||||
|
|
||||||
# Fix dns server handling before 194 / Cleanup with version 200
|
|
||||||
if DNS_SERVERS == self.servers:
|
|
||||||
self.servers.clear()
|
|
||||||
self.save_data()
|
|
||||||
|
|
||||||
# Start DNS forwarder
|
# Start DNS forwarder
|
||||||
self.sys_create_task(self.forwarder.start(self.sys_docker.network.dns))
|
self.sys_create_task(self.forwarder.start(self.sys_docker.network.dns))
|
||||||
|
|
||||||
|
@@ -84,9 +84,10 @@ class HassOS(CoreSysAttributes):
|
|||||||
url = URL_HASSOS_OTA.format(version=version, board=self.board)
|
url = URL_HASSOS_OTA.format(version=version, board=self.board)
|
||||||
raucb = Path(self.sys_config.path_tmp, f"hassos-{version}.raucb")
|
raucb = Path(self.sys_config.path_tmp, f"hassos-{version}.raucb")
|
||||||
|
|
||||||
|
_LOGGER.info("Fetch OTA update from %s", url)
|
||||||
try:
|
try:
|
||||||
_LOGGER.info("Fetch OTA update from %s", url)
|
timeout = aiohttp.ClientTimeout(total=600)
|
||||||
async with self.sys_websession.get(url) as request:
|
async with self.sys_websession.get(url, timeout=timeout) as request:
|
||||||
if request.status != 200:
|
if request.status != 200:
|
||||||
raise HassOSUpdateError()
|
raise HassOSUpdateError()
|
||||||
|
|
||||||
|
@@ -330,10 +330,6 @@ class HomeAssistant(JsonConfig, CoreSysAttributes):
|
|||||||
|
|
||||||
async def _start(self) -> None:
|
async def _start(self) -> None:
|
||||||
"""Start Home Assistant Docker & wait."""
|
"""Start Home Assistant Docker & wait."""
|
||||||
if await self.instance.is_running():
|
|
||||||
_LOGGER.warning("Home Assistant is already running!")
|
|
||||||
return
|
|
||||||
|
|
||||||
# Create new API token
|
# Create new API token
|
||||||
self._data[ATTR_ACCESS_TOKEN] = secrets.token_hex(56)
|
self._data[ATTR_ACCESS_TOKEN] = secrets.token_hex(56)
|
||||||
self.save_data()
|
self.save_data()
|
||||||
@@ -347,18 +343,21 @@ class HomeAssistant(JsonConfig, CoreSysAttributes):
|
|||||||
@process_lock
|
@process_lock
|
||||||
async def start(self) -> None:
|
async def start(self) -> None:
|
||||||
"""Run Home Assistant docker."""
|
"""Run Home Assistant docker."""
|
||||||
try:
|
if await self.instance.is_running():
|
||||||
if await self.instance.is_running():
|
_LOGGER.warning("Home Assistant is already running!")
|
||||||
await self.instance.restart()
|
return
|
||||||
elif await self.instance.is_initialize():
|
|
||||||
|
# Instance/Container exists, simple start
|
||||||
|
if await self.instance.is_initialize():
|
||||||
|
try:
|
||||||
await self.instance.start()
|
await self.instance.start()
|
||||||
else:
|
except DockerAPIError:
|
||||||
await self._start()
|
raise HomeAssistantError() from None
|
||||||
return
|
|
||||||
|
|
||||||
await self._block_till_run()
|
await self._block_till_run()
|
||||||
except DockerAPIError:
|
# No Instance/Container found, extended start
|
||||||
raise HomeAssistantError() from None
|
else:
|
||||||
|
await self._start()
|
||||||
|
|
||||||
@process_lock
|
@process_lock
|
||||||
async def stop(self) -> None:
|
async def stop(self) -> None:
|
||||||
|
@@ -73,7 +73,7 @@ class AppArmorControl(CoreSysAttributes):
|
|||||||
# Copy to AppArmor folder
|
# Copy to AppArmor folder
|
||||||
dest_profile = Path(self.sys_config.path_apparmor, profile_name)
|
dest_profile = Path(self.sys_config.path_apparmor, profile_name)
|
||||||
try:
|
try:
|
||||||
shutil.copy(profile_file, dest_profile)
|
shutil.copyfile(profile_file, dest_profile)
|
||||||
except OSError as err:
|
except OSError as err:
|
||||||
_LOGGER.error("Can't copy %s: %s", profile_file, err)
|
_LOGGER.error("Can't copy %s: %s", profile_file, err)
|
||||||
raise HostAppArmorError() from None
|
raise HostAppArmorError() from None
|
||||||
|
@@ -291,8 +291,8 @@ class SnapshotManager(CoreSysAttributes):
|
|||||||
await self.lock.acquire()
|
await self.lock.acquire()
|
||||||
|
|
||||||
async with snapshot:
|
async with snapshot:
|
||||||
# Stop Home-Assistant if they will be restored later
|
# Stop Home-Assistant for config restore
|
||||||
if homeassistant and FOLDER_HOMEASSISTANT in folders:
|
if FOLDER_HOMEASSISTANT in folders:
|
||||||
await self.sys_homeassistant.stop()
|
await self.sys_homeassistant.stop()
|
||||||
snapshot.restore_homeassistant()
|
snapshot.restore_homeassistant()
|
||||||
|
|
||||||
|
@@ -115,7 +115,7 @@ class Supervisor(CoreSysAttributes):
|
|||||||
|
|
||||||
_LOGGER.info("Update Supervisor to version %s", version)
|
_LOGGER.info("Update Supervisor to version %s", version)
|
||||||
try:
|
try:
|
||||||
await self.instance.update(version, latest=True)
|
await self.instance.install(version, image=None, latest=True)
|
||||||
except DockerAPIError:
|
except DockerAPIError:
|
||||||
_LOGGER.error("Update of Hass.io fails!")
|
_LOGGER.error("Update of Hass.io fails!")
|
||||||
raise SupervisorUpdateError() from None
|
raise SupervisorUpdateError() from None
|
||||||
|
@@ -6,7 +6,7 @@ colorlog==4.1.0
|
|||||||
cpe==1.2.1
|
cpe==1.2.1
|
||||||
cryptography==2.8
|
cryptography==2.8
|
||||||
docker==4.2.0
|
docker==4.2.0
|
||||||
gitpython==3.0.5
|
gitpython==3.0.7
|
||||||
packaging==20.1
|
packaging==20.1
|
||||||
pytz==2019.3
|
pytz==2019.3
|
||||||
pyudev==0.22.0
|
pyudev==0.22.0
|
||||||
|
@@ -67,13 +67,29 @@ function build_supervisor() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function cleanup_lastboot() {
|
||||||
|
if [[ -f /workspaces/test_supervisor/config.json ]]; then
|
||||||
|
echo "Cleaning up last boot"
|
||||||
|
cp /workspaces/test_supervisor/config.json /tmp/config.json
|
||||||
|
jq -rM 'del(.last_boot)' /tmp/config.json > /workspaces/test_supervisor/config.json
|
||||||
|
rm /tmp/config.json
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function cleanup_docker() {
|
||||||
|
echo "Cleaning up stopped containers..."
|
||||||
|
docker rm $(docker ps -a -q)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function install_cli() {
|
function install_cli() {
|
||||||
docker pull homeassistant/amd64-hassio-cli:dev
|
docker pull homeassistant/amd64-hassio-cli:dev
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function setup_test_env() {
|
function setup_test_env() {
|
||||||
mkdir -p /workspaces/test_hassio
|
mkdir -p /workspaces/test_supervisor
|
||||||
|
|
||||||
echo "Start Supervisor"
|
echo "Start Supervisor"
|
||||||
docker run --rm --privileged \
|
docker run --rm --privileged \
|
||||||
@@ -82,9 +98,9 @@ function setup_test_env() {
|
|||||||
--security-opt apparmor:unconfined \
|
--security-opt apparmor:unconfined \
|
||||||
-v /run/docker.sock:/run/docker.sock \
|
-v /run/docker.sock:/run/docker.sock \
|
||||||
-v /run/dbus:/run/dbus \
|
-v /run/dbus:/run/dbus \
|
||||||
-v "/workspaces/test_hassio":/data \
|
-v "/workspaces/test_supervisor":/data \
|
||||||
-v /etc/machine-id:/etc/machine-id:ro \
|
-v /etc/machine-id:/etc/machine-id:ro \
|
||||||
-e SUPERVISOR_SHARE="/workspaces/test_hassio" \
|
-e SUPERVISOR_SHARE="/workspaces/test_supervisor" \
|
||||||
-e SUPERVISOR_NAME=hassio_supervisor \
|
-e SUPERVISOR_NAME=hassio_supervisor \
|
||||||
-e SUPERVISOR_DEV=1 \
|
-e SUPERVISOR_DEV=1 \
|
||||||
-e HOMEASSISTANT_REPOSITORY="homeassistant/qemux86-64-homeassistant" \
|
-e HOMEASSISTANT_REPOSITORY="homeassistant/qemux86-64-homeassistant" \
|
||||||
@@ -97,12 +113,9 @@ echo "Start Test-Env"
|
|||||||
start_docker
|
start_docker
|
||||||
trap "stop_docker" ERR
|
trap "stop_docker" ERR
|
||||||
|
|
||||||
# Clean homeassistant instance
|
|
||||||
if docker rm -f homeassistant 2> /dev/null; then
|
|
||||||
echo "Cleanup HomeAssistant instance"
|
|
||||||
fi
|
|
||||||
|
|
||||||
build_supervisor
|
build_supervisor
|
||||||
install_cli
|
install_cli
|
||||||
|
cleanup_lastboot
|
||||||
|
cleanup_docker
|
||||||
setup_test_env
|
setup_test_env
|
||||||
stop_docker
|
stop_docker
|
||||||
|
Reference in New Issue
Block a user