mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-09-08 20:56:26 +00:00
Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
9f203c42ec | ||
![]() |
5d0d34a4af | ||
![]() |
c2cfc0d3d4 | ||
![]() |
0f4810d41f | ||
![]() |
175848f2a8 | ||
![]() |
472bd66f4d | ||
![]() |
168ea32d2c | ||
![]() |
e82d6b1ea4 | ||
![]() |
6c60ca088c | ||
![]() |
83e8f935fd | ||
![]() |
71867302a4 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -95,3 +95,4 @@ ENV/
|
||||
.vscode/*
|
||||
!.vscode/cSpell.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
|
18
.vscode/launch.json
vendored
Normal file
18
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Supervisor remote debug",
|
||||
"type": "python",
|
||||
"request": "attach",
|
||||
"port": 33333,
|
||||
"host": "172.30.32.2",
|
||||
"pathMappings": [
|
||||
{
|
||||
"localRoot": "${workspaceFolder}",
|
||||
"remoteRoot": "/usr/src/supervisor"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
118
API.md
118
API.md
@@ -2,7 +2,8 @@
|
||||
|
||||
## Supervisor RESTful API
|
||||
|
||||
Interface for Home Assistant to control things from supervisor.
|
||||
The RESTful API for Home Assistant allows you to control things around
|
||||
around the Supervisor and other components.
|
||||
|
||||
On error / Code 400:
|
||||
|
||||
@@ -22,8 +23,10 @@ On success / Code 200:
|
||||
}
|
||||
```
|
||||
|
||||
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.
|
||||
To access the API you need use an authorization header with a `Bearer` token.
|
||||
|
||||
The token is available for add-ons and Home Assistant using the
|
||||
`SUPERVISOR_TOKEN` environment variable.
|
||||
|
||||
### Supervisor
|
||||
|
||||
@@ -33,7 +36,7 @@ This API call don't need a token.
|
||||
|
||||
- GET `/supervisor/info`
|
||||
|
||||
The addons from `addons` are only installed one.
|
||||
Shows the installed add-ons from `addons`.
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -90,11 +93,11 @@ Optional:
|
||||
|
||||
- POST `/supervisor/reload`
|
||||
|
||||
Reload addons/version.
|
||||
Reload the add-ons/version.
|
||||
|
||||
- GET `/supervisor/logs`
|
||||
|
||||
Output is the raw docker log.
|
||||
Output is the raw Docker log.
|
||||
|
||||
- GET `/supervisor/stats`
|
||||
|
||||
@@ -113,7 +116,7 @@ Output is the raw docker log.
|
||||
|
||||
- GET `/supervisor/repair`
|
||||
|
||||
Repair overlayfs issue and restore lost images
|
||||
Repair overlayfs issue and restore lost images.
|
||||
|
||||
### Snapshot
|
||||
|
||||
@@ -134,7 +137,6 @@ Repair overlayfs issue and restore lost images
|
||||
```
|
||||
|
||||
- POST `/snapshots/reload`
|
||||
|
||||
- POST `/snapshots/new/upload`
|
||||
|
||||
return:
|
||||
@@ -208,9 +210,7 @@ return:
|
||||
```
|
||||
|
||||
- POST `/snapshots/{slug}/remove`
|
||||
|
||||
- GET `/snapshots/{slug}/download`
|
||||
|
||||
- POST `/snapshots/{slug}/restore/full`
|
||||
|
||||
```json
|
||||
@@ -233,11 +233,8 @@ return:
|
||||
### Host
|
||||
|
||||
- POST `/host/reload`
|
||||
|
||||
- POST `/host/shutdown`
|
||||
|
||||
- POST `/host/reboot`
|
||||
|
||||
- GET `/host/info`
|
||||
|
||||
```json
|
||||
@@ -254,7 +251,7 @@ return:
|
||||
|
||||
- GET `/host/logs`
|
||||
|
||||
Return host dmesg
|
||||
Return the host log messages (dmesg).
|
||||
|
||||
- POST `/host/options`
|
||||
|
||||
@@ -311,7 +308,7 @@ Return host dmesg
|
||||
|
||||
- POST `/os/config/sync`
|
||||
|
||||
Load host configs from a USB stick.
|
||||
Load host configurations from an USB stick.
|
||||
|
||||
### Hardware
|
||||
|
||||
@@ -354,7 +351,7 @@ Load host configs from a USB stick.
|
||||
|
||||
- POST `/hardware/trigger`
|
||||
|
||||
Trigger an udev reload
|
||||
Trigger an UDEV reload.
|
||||
|
||||
### Home Assistant
|
||||
|
||||
@@ -414,7 +411,7 @@ Output is the raw Docker log.
|
||||
}
|
||||
```
|
||||
|
||||
Image with `null` and version_latest with `null` reset this options.
|
||||
Image with `null` and `version_latest` with `null` reset this options.
|
||||
|
||||
- POST/GET `/core/api`
|
||||
|
||||
@@ -551,13 +548,9 @@ Get all available add-ons.
|
||||
```
|
||||
|
||||
- GET `/addons/{addon}/icon`
|
||||
|
||||
- GET `/addons/{addon}/logo`
|
||||
|
||||
- GET `/addons/{addon}/changelog`
|
||||
|
||||
- GET `/addons/{addon}/documentation`
|
||||
|
||||
- POST `/addons/{addon}/options`
|
||||
|
||||
```json
|
||||
@@ -574,7 +567,7 @@ Get all available add-ons.
|
||||
}
|
||||
```
|
||||
|
||||
Reset custom network/audio/options, set it `null`.
|
||||
Reset custom network, audio and options, set it to `null`.
|
||||
|
||||
- POST `/addons/{addon}/security`
|
||||
|
||||
@@ -587,28 +580,22 @@ This function is not callable by itself.
|
||||
```
|
||||
|
||||
- POST `/addons/{addon}/start`
|
||||
|
||||
- POST `/addons/{addon}/stop`
|
||||
|
||||
- POST `/addons/{addon}/install`
|
||||
|
||||
- POST `/addons/{addon}/uninstall`
|
||||
|
||||
- POST `/addons/{addon}/update`
|
||||
|
||||
- GET `/addons/{addon}/logs`
|
||||
|
||||
Output is the raw Docker log.
|
||||
|
||||
- POST `/addons/{addon}/restart`
|
||||
|
||||
- POST `/addons/{addon}/rebuild`
|
||||
|
||||
Only supported for local build addons
|
||||
Only supported for local build add-ons.
|
||||
|
||||
- POST `/addons/{addon}/stdin`
|
||||
|
||||
Write data to add-on stdin
|
||||
Write data to add-on stdin.
|
||||
|
||||
- GET `/addons/{addon}/stats`
|
||||
|
||||
@@ -629,7 +616,7 @@ Write data to add-on stdin
|
||||
|
||||
- POST `/ingress/session`
|
||||
|
||||
Create a new Session for access to ingress service.
|
||||
Create a new session for access to the ingress service.
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -656,8 +643,8 @@ Return a list of enabled panels.
|
||||
|
||||
- VIEW `/ingress/{token}`
|
||||
|
||||
Ingress WebUI for this Add-on. The addon need support HASS Auth!
|
||||
Need ingress session as cookie.
|
||||
Ingress WebUI for this add-on. The add-on need support for the Home Assistant
|
||||
authentication system. Needs an ingress session as cookie.
|
||||
|
||||
### discovery
|
||||
|
||||
@@ -850,57 +837,6 @@ return:
|
||||
}
|
||||
```
|
||||
|
||||
### DNS
|
||||
|
||||
- GET `/dns/info`
|
||||
|
||||
```json
|
||||
{
|
||||
"host": "ip-address",
|
||||
"version": "1",
|
||||
"version_latest": "2",
|
||||
"servers": ["dns://8.8.8.8"],
|
||||
"locals": ["dns://xy"]
|
||||
}
|
||||
```
|
||||
|
||||
- POST `/dns/options`
|
||||
|
||||
```json
|
||||
{
|
||||
"servers": ["dns://8.8.8.8"]
|
||||
}
|
||||
```
|
||||
|
||||
- POST `/dns/update`
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "VERSION"
|
||||
}
|
||||
```
|
||||
|
||||
- POST `/dns/restart`
|
||||
|
||||
- POST `/dns/reset`
|
||||
|
||||
- GET `/dns/logs`
|
||||
|
||||
- GET `/dns/stats`
|
||||
|
||||
```json
|
||||
{
|
||||
"cpu_percent": 0.0,
|
||||
"memory_usage": 283123,
|
||||
"memory_limit": 329392,
|
||||
"memory_percent": 1.4,
|
||||
"network_tx": 0,
|
||||
"network_rx": 0,
|
||||
"blk_read": 0,
|
||||
"blk_write": 0
|
||||
}
|
||||
```
|
||||
|
||||
### CLI
|
||||
|
||||
- GET `/cli/info`
|
||||
@@ -1164,18 +1100,18 @@ return:
|
||||
}
|
||||
```
|
||||
|
||||
### Auth / SSO API
|
||||
### Authentication/SSO API
|
||||
|
||||
You can use the user system on homeassistant. We handle this auth system on
|
||||
supervisor.
|
||||
You can use the user system from Home Assistant. The auth system can be handled
|
||||
with the Supervisor.
|
||||
|
||||
You can call post `/auth`
|
||||
`/auth` is accepting POST calls.
|
||||
|
||||
We support:
|
||||
|
||||
- Json `{ "user|name": "...", "password": "..." }`
|
||||
- application/x-www-form-urlencoded `user|name=...&password=...`
|
||||
- BasicAuth
|
||||
- JSON: `{ "user|name": "...", "password": "..." }`
|
||||
- `application/x-www-form-urlencoded`: `user|name=...&password=...`
|
||||
- Basic Authentication
|
||||
|
||||
* POST `/auth/reset`
|
||||
|
||||
|
24
README.md
24
README.md
@@ -2,25 +2,25 @@
|
||||
|
||||
## First private cloud solution for home automation
|
||||
|
||||
Hass.io is a Docker-based system for managing your Home Assistant installation
|
||||
and related applications. The system is controlled via Home Assistant which
|
||||
communicates with the Supervisor. The Supervisor provides an API to manage the
|
||||
installation. This includes changing network settings or installing
|
||||
and updating software.
|
||||
Home Assistant (former Hass.io) is a container-based system for managing your
|
||||
Home Assistant Core installation and related applications. The system is
|
||||
controlled via Home Assistant which communicates with the Supervisor. The
|
||||
Supervisor provides an API to manage the installation. This includes changing
|
||||
network settings or installing and updating software.
|
||||
|
||||
## Installation
|
||||
|
||||
Installation instructions can be found at <https://home-assistant.io/hassio>.
|
||||
Installation instructions can be found at https://home-assistant.io/hassio.
|
||||
|
||||
## Development
|
||||
|
||||
The development of the supervisor is a bit tricky. Not difficult but tricky.
|
||||
The development of the Supervisor is not difficult but tricky.
|
||||
|
||||
- You can use the builder to build your supervisor: https://github.com/home-assistant/hassio-builder
|
||||
- Go into a HassOS device or VM and pull your supervisor.
|
||||
- Set the developer modus with cli `hassio supervisor options --channel=dev`
|
||||
- You can use the builder to create your Supervisor: https://github.com/home-assistant/hassio-builder
|
||||
- Access a HassOS device or VM and pull your Supervisor.
|
||||
- Set the developer modus with the CLI tool: `ha supervisor options --channel=dev`
|
||||
- Tag it as `homeassistant/xy-hassio-supervisor:latest`
|
||||
- Restart the service like `systemctl restart hassos-supervisor | journalctl -fu hassos-supervisor`
|
||||
- Restart the service with `systemctl restart hassos-supervisor | journalctl -fu hassos-supervisor`
|
||||
- Test your changes
|
||||
|
||||
Small Bugfix or improvements, make a PR. Significant change makes first an RFC.
|
||||
For small bugfixes or improvements, make a PR. For significant changes open a RFC first, please. Thanks.
|
||||
|
@@ -6,8 +6,8 @@ colorlog==4.1.0
|
||||
cpe==1.2.1
|
||||
cryptography==2.9
|
||||
docker==4.2.0
|
||||
gitpython==3.1.0
|
||||
jinja2==2.11.1
|
||||
gitpython==3.1.1
|
||||
jinja2==2.11.2
|
||||
packaging==20.3
|
||||
ptvsd==4.3.2
|
||||
pulsectl==20.2.4
|
||||
|
@@ -3,7 +3,7 @@ from enum import Enum
|
||||
from ipaddress import ip_network
|
||||
from pathlib import Path
|
||||
|
||||
SUPERVISOR_VERSION = "217"
|
||||
SUPERVISOR_VERSION = "218"
|
||||
|
||||
|
||||
URL_HASSIO_ADDONS = "https://github.com/home-assistant/hassio-addons"
|
||||
|
@@ -34,6 +34,9 @@ class Core(CoreSysAttributes):
|
||||
"""Setup supervisor orchestration."""
|
||||
self.state = CoreStates.STARTUP
|
||||
|
||||
# load last available data
|
||||
await self.sys_updater.load()
|
||||
|
||||
# Load DBus
|
||||
await self.sys_dbus.load()
|
||||
|
||||
@@ -61,9 +64,6 @@ class Core(CoreSysAttributes):
|
||||
# rest api views
|
||||
await self.sys_api.load()
|
||||
|
||||
# load last available data
|
||||
await self.sys_updater.load()
|
||||
|
||||
# load last available data
|
||||
await self.sys_snapshots.load()
|
||||
|
||||
|
@@ -444,7 +444,7 @@ class DockerInterface(CoreSysAttributes):
|
||||
_LOGGER.debug("No version found for %s", self.image)
|
||||
raise DockerAPIError()
|
||||
else:
|
||||
_LOGGER.debug("Found HA versions: %s", available_version)
|
||||
_LOGGER.debug("Found %s versions: %s", self.image, available_version)
|
||||
|
||||
# Sort version and return latest version
|
||||
available_version.sort(key=key, reverse=True)
|
||||
|
@@ -77,3 +77,30 @@ class DockerSupervisor(DockerInterface, CoreSysAttributes):
|
||||
except docker.errors.DockerException as err:
|
||||
_LOGGER.error("Can't retag supervisor version: %s", err)
|
||||
raise DockerAPIError() from None
|
||||
|
||||
def update_start_tag(self, image: str, version: str) -> Awaitable[None]:
|
||||
"""Update start tag to new version."""
|
||||
return self.sys_run_in_executor(self._update_start_tag, image, version)
|
||||
|
||||
def _update_start_tag(self, image: str, version: str) -> None:
|
||||
"""Update start tag to new version.
|
||||
|
||||
Need run inside executor.
|
||||
"""
|
||||
try:
|
||||
docker_container = self.sys_docker.containers.get(self.name)
|
||||
docker_image = self.sys_docker.images.get(f"{image}:{version}")
|
||||
|
||||
# Find start tag
|
||||
for tag in docker_container.image.tags:
|
||||
start_image = tag.partition(":")[0]
|
||||
start_tag = tag.partition(":")[2] or "latest"
|
||||
|
||||
# If version tag
|
||||
if start_tag != "latest":
|
||||
continue
|
||||
docker_image.tag(start_image, start_tag)
|
||||
|
||||
except docker.errors.DockerException as err:
|
||||
_LOGGER.error("Can't fix start tag: %s", err)
|
||||
raise DockerAPIError() from None
|
||||
|
@@ -116,7 +116,10 @@ class Supervisor(CoreSysAttributes):
|
||||
_LOGGER.info("Update Supervisor to version %s", version)
|
||||
try:
|
||||
await self.instance.install(
|
||||
version, image=self.sys_updater.image_supervisor, latest=True
|
||||
version, image=self.sys_updater.image_supervisor
|
||||
)
|
||||
await self.instance.update_start_tag(
|
||||
self.sys_updater.image_supervisor, version
|
||||
)
|
||||
except DockerAPIError:
|
||||
_LOGGER.error("Update of Supervisor fails!")
|
||||
|
@@ -87,55 +87,49 @@ class Updater(JsonConfig, CoreSysAttributes):
|
||||
@property
|
||||
def image_homeassistant(self) -> Optional[str]:
|
||||
"""Return latest version of Home Assistant."""
|
||||
return (
|
||||
self._data[ATTR_IMAGE]
|
||||
.get(ATTR_HOMEASSISTANT, "")
|
||||
.format(machine=self.sys_machine)
|
||||
if ATTR_HOMEASSISTANT not in self._data[ATTR_IMAGE]:
|
||||
return None
|
||||
return self._data[ATTR_IMAGE][ATTR_HOMEASSISTANT].format(
|
||||
machine=self.sys_machine
|
||||
)
|
||||
|
||||
@property
|
||||
def image_supervisor(self) -> Optional[str]:
|
||||
"""Return latest version of Supervisor."""
|
||||
return (
|
||||
self._data[ATTR_IMAGE]
|
||||
.get(ATTR_SUPERVISOR, "")
|
||||
.format(arch=self.sys_arch.supervisor)
|
||||
if ATTR_SUPERVISOR not in self._data[ATTR_IMAGE]:
|
||||
return None
|
||||
return self._data[ATTR_IMAGE][ATTR_SUPERVISOR].format(
|
||||
arch=self.sys_arch.supervisor
|
||||
)
|
||||
|
||||
@property
|
||||
def image_cli(self) -> Optional[str]:
|
||||
"""Return latest version of CLI."""
|
||||
return (
|
||||
self._data[ATTR_IMAGE]
|
||||
.get(ATTR_CLI, "")
|
||||
.format(arch=self.sys_arch.supervisor)
|
||||
)
|
||||
if ATTR_CLI not in self._data[ATTR_IMAGE]:
|
||||
return None
|
||||
return self._data[ATTR_IMAGE][ATTR_CLI].format(arch=self.sys_arch.supervisor)
|
||||
|
||||
@property
|
||||
def image_dns(self) -> Optional[str]:
|
||||
"""Return latest version of DNS."""
|
||||
return (
|
||||
self._data[ATTR_IMAGE]
|
||||
.get(ATTR_DNS, "")
|
||||
.format(arch=self.sys_arch.supervisor)
|
||||
)
|
||||
if ATTR_DNS not in self._data[ATTR_IMAGE]:
|
||||
return None
|
||||
return self._data[ATTR_IMAGE][ATTR_DNS].format(arch=self.sys_arch.supervisor)
|
||||
|
||||
@property
|
||||
def image_audio(self) -> Optional[str]:
|
||||
"""Return latest version of Audio."""
|
||||
return (
|
||||
self._data[ATTR_IMAGE]
|
||||
.get(ATTR_AUDIO, "")
|
||||
.format(arch=self.sys_arch.supervisor)
|
||||
)
|
||||
if ATTR_AUDIO not in self._data[ATTR_IMAGE]:
|
||||
return None
|
||||
return self._data[ATTR_IMAGE][ATTR_AUDIO].format(arch=self.sys_arch.supervisor)
|
||||
|
||||
@property
|
||||
def image_multicast(self) -> Optional[str]:
|
||||
"""Return latest version of Multicast."""
|
||||
return (
|
||||
self._data[ATTR_IMAGE]
|
||||
.get(ATTR_MULTICAST, "")
|
||||
.format(arch=self.sys_arch.supervisor)
|
||||
if ATTR_MULTICAST not in self._data[ATTR_IMAGE]:
|
||||
return None
|
||||
return self._data[ATTR_IMAGE][ATTR_MULTICAST].format(
|
||||
arch=self.sys_arch.supervisor
|
||||
)
|
||||
|
||||
@property
|
||||
|
Reference in New Issue
Block a user