ha-supervisor/supervisor/api/__init__.py

690 lines
26 KiB
Python
Raw Normal View History

"""Init file for Supervisor RESTful API."""
Add enhanced logging REST endpoints using systemd-journal-gatewayd (#3291) * Add enhanced logging REST endpoints using systemd-journal-gatewayd Add /host/logs/entries and /host/logs/{identifier}/entries to expose log entries from systemd-journald running on the host. Use systemd-journal-gatewayd which exposes the logs to the Supervisor via Unix socket. Current two query string parameters are allowed: "boot" and "follow". The first will only return logs since last boot. The second will keep the HTTP request open and send new log entries as they get added to the systemd-journal. * Allow Range header Forward the Range header to systemd-journal-gatewayd. This allows to select only a certain amount of log data. The Range header is a standard header to select only partial amount of data. However, the "entries=" prefix is custom for systemd-journal-gatewayd, denoting that the numbers following represent log entries (as opposed to bytes or other metrics). * Avoid connecting if systemd-journal-gatewayd is not available * Use path for all options * Add pytests * Address pylint issues * Boot ID offsets and slug to identifier * Fix tests * API refactor from feedback * fix tests and add identifiers * stop isort and pylint fighting * fix tests * Update default log identifiers * Only modify /host/logs endpoints * Fix bad import * Load log caches asynchronously at startup * Allow task to complete in fixture * Boot IDs and identifiers loaded on demand * Add suggested identifiers * Fix tests around boot ids Co-authored-by: Mike Degatano <michael.degatano@gmail.com>
2022-10-13 17:40:11 +02:00
from functools import partial
2017-03-30 16:01:52 +02:00
import logging
from pathlib import Path
from typing import Any
2017-03-30 16:01:52 +02:00
from aiohttp import web
from ..const import AddonState
from ..coresys import CoreSys, CoreSysAttributes
from ..exceptions import APIAddonNotInstalled
2017-04-12 22:59:40 +02:00
from .addons import APIAddons
from .audio import APIAudio
from .auth import APIAuth
2021-07-27 10:06:09 +02:00
from .backups import APIBackups
from .cli import APICli
Add support to expose internal services (#339) * Init services discovery * extend it * Add mqtt provider * Service support * More protocol stuff * Update validate.py * Update validate.py * Update API.md * Update API.md * update api * add API for services * fix lint * add security middleware * Add discovery layout * update * Finish discovery * improve discovery * fix * Update API * Update api * fix * Fix lint * Update API.md * Update __init__.py * Update API.md * Update interface.py * Update mqtt.py * Update discovery.py * Update const.py * Update validate.py * Update validate.py * Update mqtt.py * Update mqtt.py * Update discovery.py * Update discovery.py * Update discovery.py * Update interface.py * Update mqtt.py * Update mqtt.py * Update services.py * Update discovery.py * Update discovery.py * Update mqtt.py * Update discovery.py * Update services.py * Update discovery.py * Update discovery.py * Update mqtt.py * Update discovery.py * fix aiohttp * test * Update const.py * Update addon.py * Update homeassistant.py * Update const.py * Update addon.py * Update homeassistant.py * Update addon.py * Update security.py * Update const.py * Update validate.py * Update const.py * Update addon.py * Update API.md * Update addons.py * Update addon.py * Update validate.py * Update security.py * Update security.py * Update const.py * Update services.py * Update discovery.py * Update API.md * Update services.py * Update API.md * Update services.py * Update discovery.py * Update discovery.py * Update mqtt.py * Update discovery.py * Update discovery.py * Update __init__.py * Update mqtt.py * Update security.py * fix lint * Update core.py * Update API.md * Update services.py
2018-02-08 17:19:47 +01:00
from .discovery import APIDiscovery
from .dns import APICoreDNS
from .docker import APIDocker
2018-04-12 22:15:08 +02:00
from .hardware import APIHardware
from .homeassistant import APIHomeAssistant
from .host import APIHost
from .ingress import APIIngress
from .jobs import APIJobs
from .middleware.security import SecurityMiddleware
from .mounts import APIMounts
from .multicast import APIMulticast
from .network import APINetwork
from .observer import APIObserver
from .os import APIOS
from .proxy import APIProxy
from .resolution import APIResoulution
from .root import APIRoot
from .security import APISecurity
from .services import APIServices
2021-02-25 16:15:51 +01:00
from .store import APIStore
from .supervisor import APISupervisor
from .utils import api_process
2017-03-30 16:01:52 +02:00
_LOGGER: logging.Logger = logging.getLogger(__name__)
2017-03-30 16:01:52 +02:00
MAX_CLIENT_SIZE: int = 1024**2 * 16
MAX_LINE_SIZE: int = 24570
class RestAPI(CoreSysAttributes):
"""Handle RESTful API for Supervisor."""
2017-03-30 16:01:52 +02:00
def __init__(self, coresys: CoreSys):
"""Initialize Docker base wrapper."""
self.coresys: CoreSys = coresys
self.security: SecurityMiddleware = SecurityMiddleware(coresys)
self.webapp: web.Application = web.Application(
client_max_size=MAX_CLIENT_SIZE,
middlewares=[
2023-03-01 08:52:19 +01:00
self.security.block_bad_requests,
self.security.system_validation,
self.security.token_validation,
self.security.core_proxy,
],
handler_args={
"max_line_size": MAX_LINE_SIZE,
"max_field_size": MAX_LINE_SIZE,
},
2019-05-27 12:35:06 +02:00
)
2017-03-30 16:01:52 +02:00
2017-03-30 23:26:26 +02:00
# service stuff
self._runner: web.AppRunner = web.AppRunner(self.webapp)
self._site: web.TCPSite | None = None
2017-03-30 16:01:52 +02:00
async def load(self) -> None:
"""Register REST API Calls."""
2020-10-06 11:26:56 +02:00
self._register_addons()
self._register_audio()
self._register_auth()
2021-07-27 10:06:09 +02:00
self._register_backups()
self._register_cli()
2020-10-06 11:26:56 +02:00
self._register_discovery()
self._register_dns()
self._register_docker()
2018-04-12 22:15:08 +02:00
self._register_hardware()
self._register_homeassistant()
2020-10-06 11:26:56 +02:00
self._register_host()
self._register_jobs()
self._register_ingress()
self._register_mounts()
2020-10-06 11:26:56 +02:00
self._register_multicast()
self._register_network()
self._register_observer()
self._register_os()
self._register_panel()
self._register_proxy()
self._register_resolution()
self._register_root()
self._register_security()
Add support to expose internal services (#339) * Init services discovery * extend it * Add mqtt provider * Service support * More protocol stuff * Update validate.py * Update validate.py * Update API.md * Update API.md * update api * add API for services * fix lint * add security middleware * Add discovery layout * update * Finish discovery * improve discovery * fix * Update API * Update api * fix * Fix lint * Update API.md * Update __init__.py * Update API.md * Update interface.py * Update mqtt.py * Update discovery.py * Update const.py * Update validate.py * Update validate.py * Update mqtt.py * Update mqtt.py * Update discovery.py * Update discovery.py * Update discovery.py * Update interface.py * Update mqtt.py * Update mqtt.py * Update services.py * Update discovery.py * Update discovery.py * Update mqtt.py * Update discovery.py * Update services.py * Update discovery.py * Update discovery.py * Update mqtt.py * Update discovery.py * fix aiohttp * test * Update const.py * Update addon.py * Update homeassistant.py * Update const.py * Update addon.py * Update homeassistant.py * Update addon.py * Update security.py * Update const.py * Update validate.py * Update const.py * Update addon.py * Update API.md * Update addons.py * Update addon.py * Update validate.py * Update security.py * Update security.py * Update const.py * Update services.py * Update discovery.py * Update API.md * Update services.py * Update API.md * Update services.py * Update discovery.py * Update discovery.py * Update mqtt.py * Update discovery.py * Update discovery.py * Update __init__.py * Update mqtt.py * Update security.py * fix lint * Update core.py * Update API.md * Update services.py
2018-02-08 17:19:47 +01:00
self._register_services()
2021-02-25 16:15:51 +01:00
self._register_store()
self._register_supervisor()
2020-10-23 16:48:03 +02:00
await self.start()
def _register_host(self) -> None:
"""Register hostcontrol functions."""
api_host = APIHost()
api_host.coresys = self.coresys
2017-03-30 16:01:52 +02:00
2019-05-27 12:35:06 +02:00
self.webapp.add_routes(
[
web.get("/host/info", api_host.info),
Add enhanced logging REST endpoints using systemd-journal-gatewayd (#3291) * Add enhanced logging REST endpoints using systemd-journal-gatewayd Add /host/logs/entries and /host/logs/{identifier}/entries to expose log entries from systemd-journald running on the host. Use systemd-journal-gatewayd which exposes the logs to the Supervisor via Unix socket. Current two query string parameters are allowed: "boot" and "follow". The first will only return logs since last boot. The second will keep the HTTP request open and send new log entries as they get added to the systemd-journal. * Allow Range header Forward the Range header to systemd-journal-gatewayd. This allows to select only a certain amount of log data. The Range header is a standard header to select only partial amount of data. However, the "entries=" prefix is custom for systemd-journal-gatewayd, denoting that the numbers following represent log entries (as opposed to bytes or other metrics). * Avoid connecting if systemd-journal-gatewayd is not available * Use path for all options * Add pytests * Address pylint issues * Boot ID offsets and slug to identifier * Fix tests * API refactor from feedback * fix tests and add identifiers * stop isort and pylint fighting * fix tests * Update default log identifiers * Only modify /host/logs endpoints * Fix bad import * Load log caches asynchronously at startup * Allow task to complete in fixture * Boot IDs and identifiers loaded on demand * Add suggested identifiers * Fix tests around boot ids Co-authored-by: Mike Degatano <michael.degatano@gmail.com>
2022-10-13 17:40:11 +02:00
web.get("/host/logs", api_host.advanced_logs),
web.get(
"/host/logs/follow",
partial(api_host.advanced_logs, follow=True),
),
web.get("/host/logs/identifiers", api_host.list_identifiers),
web.get("/host/logs/identifiers/{identifier}", api_host.advanced_logs),
web.get(
"/host/logs/identifiers/{identifier}/follow",
partial(api_host.advanced_logs, follow=True),
),
web.get("/host/logs/boots", api_host.list_boots),
web.get("/host/logs/boots/{bootid}", api_host.advanced_logs),
web.get(
"/host/logs/boots/{bootid}/follow",
partial(api_host.advanced_logs, follow=True),
),
web.get(
"/host/logs/boots/{bootid}/identifiers/{identifier}",
api_host.advanced_logs,
),
web.get(
"/host/logs/boots/{bootid}/identifiers/{identifier}/follow",
partial(api_host.advanced_logs, follow=True),
),
2019-05-27 12:35:06 +02:00
web.post("/host/reboot", api_host.reboot),
web.post("/host/shutdown", api_host.shutdown),
web.post("/host/reload", api_host.reload),
web.post("/host/options", api_host.options),
web.get("/host/services", api_host.services),
]
)
2017-04-05 08:55:19 +02:00
def _register_network(self) -> None:
"""Register network functions."""
api_network = APINetwork()
api_network.coresys = self.coresys
self.webapp.add_routes(
[
web.get("/network/info", api_network.info),
2020-12-01 14:03:59 +01:00
web.post("/network/reload", api_network.reload),
web.get(
"/network/interface/{interface}/info", api_network.interface_info
),
web.post(
"/network/interface/{interface}/update",
api_network.interface_update,
),
Network: abstract dbus and supervisor - ipv6/wifi/vlan (#2217) * Abstract code between dbus - supervisor * cleanup v2 * fix address vs interface * fix API calls * Fix methodnames * add vlan type * add vlan support * Fix tests * Add wifi support * more OOO * fix typing import * typing part 2 * Fix profile * fix test payload * ignore powersafe * support privancy * fix property * Fix tests * full support all API * Fix all * more robust * Update supervisor/dbus/network/connection.py Co-authored-by: Joakim Sørensen <joasoe@gmail.com> * Fix gateway * fix empty gateway * Allow no ipv6 or ipv4 kernel support * Exclude device drivers * Add wifi * Use loop on api * refactory p1 Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch> * refactory p2 Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch> * refactory p3 Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch> * refactory p4 Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch> * refactory p5 Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch> * refactory p6 Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch> * refactory p7 Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch> * refactory p8 Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch> * Fix lint * update sup p1 Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch> * update sup p2 Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch> * fix tests Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch> * fix logging Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch> * improve mock handling Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch> * add fixtures Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch> * fix tests * better testing * Add more tests * Fix API test * Add test for vlan payload * Support variation * Fix doc string * support remove & wifi scan * make sure we ignore local-link on ipv6 * remove privancy - add vlan * Fix tests * fix isort * Fixture dbus by commands * Add dnsmanager fixture * expose commands called by dbus * Add wifi tests * Update supervisor/plugins/dns.py Co-authored-by: Joakim Sørensen <joasoe@gmail.com> * Address comments & fix tests * change url to be closer on others Co-authored-by: Joakim Sørensen <joasoe@gmail.com>
2020-11-09 08:56:42 +01:00
web.get(
"/network/interface/{interface}/accesspoints",
api_network.scan_accesspoints,
),
web.post(
"/network/interface/{interface}/vlan/{vlan}",
api_network.create_vlan,
),
]
)
def _register_os(self) -> None:
"""Register OS functions."""
api_os = APIOS()
api_os.coresys = self.coresys
self.webapp.add_routes(
[
web.get("/os/info", api_os.info),
web.post("/os/update", api_os.update),
web.post("/os/config/sync", api_os.config_sync),
web.post("/os/datadisk/move", api_os.migrate_data),
web.get("/os/datadisk/list", api_os.list_data),
]
)
# Boards endpoints
self.webapp.add_routes(
[
web.get("/os/boards/yellow", api_os.boards_yellow_info),
web.post("/os/boards/yellow", api_os.boards_yellow_options),
web.get("/os/boards/{board}", api_os.boards_other_info),
]
)
def _register_security(self) -> None:
"""Register Security functions."""
api_security = APISecurity()
api_security.coresys = self.coresys
self.webapp.add_routes(
[
web.get("/security/info", api_security.info),
web.post("/security/options", api_security.options),
web.post("/security/integrity", api_security.integrity_check),
]
)
def _register_jobs(self) -> None:
"""Register Jobs functions."""
api_jobs = APIJobs()
api_jobs.coresys = self.coresys
self.webapp.add_routes(
[
web.get("/jobs/info", api_jobs.info),
web.post("/jobs/options", api_jobs.options),
web.post("/jobs/reset", api_jobs.reset),
]
)
def _register_cli(self) -> None:
"""Register HA cli functions."""
api_cli = APICli()
api_cli.coresys = self.coresys
2019-05-27 12:35:06 +02:00
self.webapp.add_routes(
[
web.get("/cli/info", api_cli.info),
web.get("/cli/stats", api_cli.stats),
web.post("/cli/update", api_cli.update),
2019-05-27 12:35:06 +02:00
]
)
def _register_observer(self) -> None:
"""Register Observer functions."""
api_observer = APIObserver()
api_observer.coresys = self.coresys
self.webapp.add_routes(
[
web.get("/observer/info", api_observer.info),
web.get("/observer/stats", api_observer.stats),
web.post("/observer/update", api_observer.update),
]
)
def _register_multicast(self) -> None:
"""Register Multicast functions."""
api_multicast = APIMulticast()
api_multicast.coresys = self.coresys
self.webapp.add_routes(
[
web.get("/multicast/info", api_multicast.info),
web.get("/multicast/stats", api_multicast.stats),
2020-04-08 14:08:09 +02:00
web.get("/multicast/logs", api_multicast.logs),
web.post("/multicast/update", api_multicast.update),
web.post("/multicast/restart", api_multicast.restart),
]
)
def _register_hardware(self) -> None:
"""Register hardware functions."""
2018-04-12 22:15:08 +02:00
api_hardware = APIHardware()
api_hardware.coresys = self.coresys
2019-05-27 12:35:06 +02:00
self.webapp.add_routes(
[
web.get("/hardware/info", api_hardware.info),
web.get("/hardware/audio", api_hardware.audio),
]
)
2018-04-12 22:15:08 +02:00
def _register_root(self) -> None:
"""Register root functions."""
api_root = APIRoot()
api_root.coresys = self.coresys
self.webapp.add_routes([web.get("/info", api_root.info)])
self.webapp.add_routes([web.post("/refresh_updates", api_root.refresh_updates)])
self.webapp.add_routes(
[web.get("/available_updates", api_root.available_updates)]
)
# Remove: 2023
self.webapp.add_routes(
[web.get("/supervisor/available_updates", api_root.available_updates)]
)
def _register_resolution(self) -> None:
"""Register info functions."""
api_resolution = APIResoulution()
api_resolution.coresys = self.coresys
self.webapp.add_routes(
[
2020-10-16 13:07:02 +02:00
web.get("/resolution/info", api_resolution.info),
web.post(
"/resolution/check/{check}/options", api_resolution.options_check
),
web.post("/resolution/check/{check}/run", api_resolution.run_check),
web.post(
"/resolution/suggestion/{suggestion}",
api_resolution.apply_suggestion,
),
web.delete(
"/resolution/suggestion/{suggestion}",
api_resolution.dismiss_suggestion,
),
web.delete(
"/resolution/issue/{issue}",
api_resolution.dismiss_issue,
),
web.get(
"/resolution/issue/{issue}/suggestions",
api_resolution.suggestions_for_issue,
),
web.post("/resolution/healthcheck", api_resolution.healthcheck),
]
)
def _register_auth(self) -> None:
"""Register auth functions."""
api_auth = APIAuth()
api_auth.coresys = self.coresys
self.webapp.add_routes(
[
web.get("/auth", api_auth.auth),
web.post("/auth", api_auth.auth),
web.post("/auth/reset", api_auth.reset),
web.delete("/auth/cache", api_auth.cache),
]
)
def _register_supervisor(self) -> None:
"""Register Supervisor functions."""
api_supervisor = APISupervisor()
api_supervisor.coresys = self.coresys
2017-03-30 16:54:13 +02:00
2019-05-27 12:35:06 +02:00
self.webapp.add_routes(
[
web.get("/supervisor/ping", api_supervisor.ping),
web.get("/supervisor/info", api_supervisor.info),
web.get("/supervisor/stats", api_supervisor.stats),
web.get("/supervisor/logs", api_supervisor.logs),
web.post("/supervisor/update", api_supervisor.update),
web.post("/supervisor/reload", api_supervisor.reload),
web.post("/supervisor/restart", api_supervisor.restart),
2019-05-27 12:35:06 +02:00
web.post("/supervisor/options", api_supervisor.options),
web.post("/supervisor/repair", api_supervisor.repair),
2019-05-27 12:35:06 +02:00
]
)
2017-03-30 16:54:13 +02:00
def _register_homeassistant(self) -> None:
"""Register Home Assistant functions."""
api_hass = APIHomeAssistant()
api_hass.coresys = self.coresys
2017-03-30 16:01:52 +02:00
2019-05-27 12:35:06 +02:00
self.webapp.add_routes(
[
web.get("/core/info", api_hass.info),
web.get("/core/logs", api_hass.logs),
web.get("/core/stats", api_hass.stats),
web.post("/core/options", api_hass.options),
web.post("/core/update", api_hass.update),
web.post("/core/restart", api_hass.restart),
web.post("/core/stop", api_hass.stop),
web.post("/core/start", api_hass.start),
web.post("/core/check", api_hass.check),
web.post("/core/rebuild", api_hass.rebuild),
]
)
# Reroute from legacy
self.webapp.add_routes(
[
2019-05-27 12:35:06 +02:00
web.get("/homeassistant/info", api_hass.info),
web.get("/homeassistant/logs", api_hass.logs),
web.get("/homeassistant/stats", api_hass.stats),
web.post("/homeassistant/options", api_hass.options),
web.post("/homeassistant/restart", api_hass.restart),
web.post("/homeassistant/stop", api_hass.stop),
web.post("/homeassistant/start", api_hass.start),
web.post("/homeassistant/update", api_hass.update),
2019-05-27 12:35:06 +02:00
web.post("/homeassistant/rebuild", api_hass.rebuild),
web.post("/homeassistant/check", api_hass.check),
2019-05-27 12:35:06 +02:00
]
)
def _register_proxy(self) -> None:
"""Register Home Assistant API Proxy."""
api_proxy = APIProxy()
api_proxy.coresys = self.coresys
2019-05-27 12:35:06 +02:00
self.webapp.add_routes(
[
web.get("/core/api/websocket", api_proxy.websocket),
web.get("/core/websocket", api_proxy.websocket),
web.get("/core/api/stream", api_proxy.stream),
web.post("/core/api/{path:.+}", api_proxy.api),
web.get("/core/api/{path:.+}", api_proxy.api),
web.get("/core/api/", api_proxy.api),
]
)
# Reroute from legacy
self.webapp.add_routes(
[
2019-05-27 12:35:06 +02:00
web.get("/homeassistant/api/websocket", api_proxy.websocket),
web.get("/homeassistant/websocket", api_proxy.websocket),
web.get("/homeassistant/api/stream", api_proxy.stream),
web.post("/homeassistant/api/{path:.+}", api_proxy.api),
web.get("/homeassistant/api/{path:.+}", api_proxy.api),
web.get("/homeassistant/api/", api_proxy.api),
]
)
2017-03-30 16:01:52 +02:00
def _register_addons(self) -> None:
"""Register Add-on functions."""
api_addons = APIAddons()
api_addons.coresys = self.coresys
2017-04-12 00:06:17 +02:00
2019-05-27 12:35:06 +02:00
self.webapp.add_routes(
[
web.get("/addons", api_addons.list),
web.post("/addons/{addon}/uninstall", api_addons.uninstall),
web.post("/addons/{addon}/start", api_addons.start),
web.post("/addons/{addon}/stop", api_addons.stop),
web.post("/addons/{addon}/restart", api_addons.restart),
web.post("/addons/{addon}/options", api_addons.options),
2020-08-30 17:58:13 +02:00
web.post(
"/addons/{addon}/options/validate", api_addons.options_validate
),
web.get("/addons/{addon}/options/config", api_addons.options_config),
2019-05-27 12:35:06 +02:00
web.post("/addons/{addon}/rebuild", api_addons.rebuild),
web.get("/addons/{addon}/logs", api_addons.logs),
web.post("/addons/{addon}/stdin", api_addons.stdin),
web.post("/addons/{addon}/security", api_addons.security),
web.get("/addons/{addon}/stats", api_addons.stats),
]
)
2017-04-12 00:06:17 +02:00
# Legacy routing to support requests for not installed addons
api_store = APIStore()
api_store.coresys = self.coresys
@api_process
async def addons_addon_info(request: web.Request) -> dict[str, Any]:
"""Route to store if info requested for not installed addon."""
try:
return await api_addons.info(request)
except APIAddonNotInstalled:
# Route to store/{addon}/info but add missing fields
return dict(
await api_store.addons_addon_info_wrapped(request),
state=AddonState.UNKNOWN,
options=self.sys_addons.store[request.match_info["addon"]].options,
)
self.webapp.add_routes([web.get("/addons/{addon}/info", addons_addon_info)])
def _register_ingress(self) -> None:
"""Register Ingress functions."""
api_ingress = APIIngress()
api_ingress.coresys = self.coresys
2019-05-27 12:35:06 +02:00
self.webapp.add_routes(
[
web.post("/ingress/session", api_ingress.create_session),
2020-11-06 11:52:11 +01:00
web.post("/ingress/validate_session", api_ingress.validate_session),
2019-05-27 12:35:06 +02:00
web.get("/ingress/panels", api_ingress.panels),
web.view("/ingress/{token}/{path:.*}", api_ingress.handler),
]
)
2021-07-27 10:06:09 +02:00
def _register_backups(self) -> None:
"""Register backups functions."""
api_backups = APIBackups()
api_backups.coresys = self.coresys
2019-05-27 12:35:06 +02:00
self.webapp.add_routes(
[
2021-07-27 10:06:09 +02:00
web.get("/backups", api_backups.list),
web.get("/backups/info", api_backups.info),
web.post("/backups/options", api_backups.options),
2021-07-27 10:06:09 +02:00
web.post("/backups/reload", api_backups.reload),
web.post("/backups/new/full", api_backups.backup_full),
web.post("/backups/new/partial", api_backups.backup_partial),
web.post("/backups/new/upload", api_backups.upload),
web.get("/backups/{slug}/info", api_backups.backup_info),
2021-07-27 10:06:09 +02:00
web.delete("/backups/{slug}", api_backups.remove),
web.post("/backups/{slug}/restore/full", api_backups.restore_full),
2019-05-27 12:35:06 +02:00
web.post(
2021-07-27 10:06:09 +02:00
"/backups/{slug}/restore/partial",
api_backups.restore_partial,
2019-05-27 12:35:06 +02:00
),
2021-07-27 10:06:09 +02:00
web.get("/backups/{slug}/download", api_backups.download),
2019-05-27 12:35:06 +02:00
]
)
def _register_services(self) -> None:
"""Register services functions."""
Add support to expose internal services (#339) * Init services discovery * extend it * Add mqtt provider * Service support * More protocol stuff * Update validate.py * Update validate.py * Update API.md * Update API.md * update api * add API for services * fix lint * add security middleware * Add discovery layout * update * Finish discovery * improve discovery * fix * Update API * Update api * fix * Fix lint * Update API.md * Update __init__.py * Update API.md * Update interface.py * Update mqtt.py * Update discovery.py * Update const.py * Update validate.py * Update validate.py * Update mqtt.py * Update mqtt.py * Update discovery.py * Update discovery.py * Update discovery.py * Update interface.py * Update mqtt.py * Update mqtt.py * Update services.py * Update discovery.py * Update discovery.py * Update mqtt.py * Update discovery.py * Update services.py * Update discovery.py * Update discovery.py * Update mqtt.py * Update discovery.py * fix aiohttp * test * Update const.py * Update addon.py * Update homeassistant.py * Update const.py * Update addon.py * Update homeassistant.py * Update addon.py * Update security.py * Update const.py * Update validate.py * Update const.py * Update addon.py * Update API.md * Update addons.py * Update addon.py * Update validate.py * Update security.py * Update security.py * Update const.py * Update services.py * Update discovery.py * Update API.md * Update services.py * Update API.md * Update services.py * Update discovery.py * Update discovery.py * Update mqtt.py * Update discovery.py * Update discovery.py * Update __init__.py * Update mqtt.py * Update security.py * fix lint * Update core.py * Update API.md * Update services.py
2018-02-08 17:19:47 +01:00
api_services = APIServices()
api_services.coresys = self.coresys
2019-05-27 12:35:06 +02:00
self.webapp.add_routes(
[
web.get("/services", api_services.list),
web.get("/services/{service}", api_services.get_service),
web.post("/services/{service}", api_services.set_service),
web.delete("/services/{service}", api_services.del_service),
]
)
Add support to expose internal services (#339) * Init services discovery * extend it * Add mqtt provider * Service support * More protocol stuff * Update validate.py * Update validate.py * Update API.md * Update API.md * update api * add API for services * fix lint * add security middleware * Add discovery layout * update * Finish discovery * improve discovery * fix * Update API * Update api * fix * Fix lint * Update API.md * Update __init__.py * Update API.md * Update interface.py * Update mqtt.py * Update discovery.py * Update const.py * Update validate.py * Update validate.py * Update mqtt.py * Update mqtt.py * Update discovery.py * Update discovery.py * Update discovery.py * Update interface.py * Update mqtt.py * Update mqtt.py * Update services.py * Update discovery.py * Update discovery.py * Update mqtt.py * Update discovery.py * Update services.py * Update discovery.py * Update discovery.py * Update mqtt.py * Update discovery.py * fix aiohttp * test * Update const.py * Update addon.py * Update homeassistant.py * Update const.py * Update addon.py * Update homeassistant.py * Update addon.py * Update security.py * Update const.py * Update validate.py * Update const.py * Update addon.py * Update API.md * Update addons.py * Update addon.py * Update validate.py * Update security.py * Update security.py * Update const.py * Update services.py * Update discovery.py * Update API.md * Update services.py * Update API.md * Update services.py * Update discovery.py * Update discovery.py * Update mqtt.py * Update discovery.py * Update discovery.py * Update __init__.py * Update mqtt.py * Update security.py * fix lint * Update core.py * Update API.md * Update services.py
2018-02-08 17:19:47 +01:00
def _register_discovery(self) -> None:
"""Register discovery functions."""
Add support to expose internal services (#339) * Init services discovery * extend it * Add mqtt provider * Service support * More protocol stuff * Update validate.py * Update validate.py * Update API.md * Update API.md * update api * add API for services * fix lint * add security middleware * Add discovery layout * update * Finish discovery * improve discovery * fix * Update API * Update api * fix * Fix lint * Update API.md * Update __init__.py * Update API.md * Update interface.py * Update mqtt.py * Update discovery.py * Update const.py * Update validate.py * Update validate.py * Update mqtt.py * Update mqtt.py * Update discovery.py * Update discovery.py * Update discovery.py * Update interface.py * Update mqtt.py * Update mqtt.py * Update services.py * Update discovery.py * Update discovery.py * Update mqtt.py * Update discovery.py * Update services.py * Update discovery.py * Update discovery.py * Update mqtt.py * Update discovery.py * fix aiohttp * test * Update const.py * Update addon.py * Update homeassistant.py * Update const.py * Update addon.py * Update homeassistant.py * Update addon.py * Update security.py * Update const.py * Update validate.py * Update const.py * Update addon.py * Update API.md * Update addons.py * Update addon.py * Update validate.py * Update security.py * Update security.py * Update const.py * Update services.py * Update discovery.py * Update API.md * Update services.py * Update API.md * Update services.py * Update discovery.py * Update discovery.py * Update mqtt.py * Update discovery.py * Update discovery.py * Update __init__.py * Update mqtt.py * Update security.py * fix lint * Update core.py * Update API.md * Update services.py
2018-02-08 17:19:47 +01:00
api_discovery = APIDiscovery()
api_discovery.coresys = self.coresys
2019-05-27 12:35:06 +02:00
self.webapp.add_routes(
[
web.get("/discovery", api_discovery.list),
web.get("/discovery/{uuid}", api_discovery.get_discovery),
web.delete("/discovery/{uuid}", api_discovery.del_discovery),
web.post("/discovery", api_discovery.set_discovery),
]
)
def _register_dns(self) -> None:
"""Register DNS functions."""
api_dns = APICoreDNS()
api_dns.coresys = self.coresys
self.webapp.add_routes(
[
web.get("/dns/info", api_dns.info),
web.get("/dns/stats", api_dns.stats),
web.get("/dns/logs", api_dns.logs),
web.post("/dns/update", api_dns.update),
web.post("/dns/options", api_dns.options),
web.post("/dns/restart", api_dns.restart),
2020-01-09 22:27:39 +01:00
web.post("/dns/reset", api_dns.reset),
]
)
def _register_audio(self) -> None:
"""Register Audio functions."""
api_audio = APIAudio()
api_audio.coresys = self.coresys
Add enhanced logging REST endpoints using systemd-journal-gatewayd (#3291) * Add enhanced logging REST endpoints using systemd-journal-gatewayd Add /host/logs/entries and /host/logs/{identifier}/entries to expose log entries from systemd-journald running on the host. Use systemd-journal-gatewayd which exposes the logs to the Supervisor via Unix socket. Current two query string parameters are allowed: "boot" and "follow". The first will only return logs since last boot. The second will keep the HTTP request open and send new log entries as they get added to the systemd-journal. * Allow Range header Forward the Range header to systemd-journal-gatewayd. This allows to select only a certain amount of log data. The Range header is a standard header to select only partial amount of data. However, the "entries=" prefix is custom for systemd-journal-gatewayd, denoting that the numbers following represent log entries (as opposed to bytes or other metrics). * Avoid connecting if systemd-journal-gatewayd is not available * Use path for all options * Add pytests * Address pylint issues * Boot ID offsets and slug to identifier * Fix tests * API refactor from feedback * fix tests and add identifiers * stop isort and pylint fighting * fix tests * Update default log identifiers * Only modify /host/logs endpoints * Fix bad import * Load log caches asynchronously at startup * Allow task to complete in fixture * Boot IDs and identifiers loaded on demand * Add suggested identifiers * Fix tests around boot ids Co-authored-by: Mike Degatano <michael.degatano@gmail.com>
2022-10-13 17:40:11 +02:00
api_host = APIHost()
api_host.coresys = self.coresys
self.webapp.add_routes(
[
web.get("/audio/info", api_audio.info),
web.get("/audio/stats", api_audio.stats),
web.get("/audio/logs", api_audio.logs),
web.post("/audio/update", api_audio.update),
web.post("/audio/restart", api_audio.restart),
web.post("/audio/reload", api_audio.reload),
web.post("/audio/profile", api_audio.set_profile),
web.post("/audio/volume/{source}/application", api_audio.set_volume),
web.post("/audio/volume/{source}", api_audio.set_volume),
web.post("/audio/mute/{source}/application", api_audio.set_mute),
web.post("/audio/mute/{source}", api_audio.set_mute),
web.post("/audio/default/{source}", api_audio.set_default),
2019-05-27 12:35:06 +02:00
]
)
Add support to expose internal services (#339) * Init services discovery * extend it * Add mqtt provider * Service support * More protocol stuff * Update validate.py * Update validate.py * Update API.md * Update API.md * update api * add API for services * fix lint * add security middleware * Add discovery layout * update * Finish discovery * improve discovery * fix * Update API * Update api * fix * Fix lint * Update API.md * Update __init__.py * Update API.md * Update interface.py * Update mqtt.py * Update discovery.py * Update const.py * Update validate.py * Update validate.py * Update mqtt.py * Update mqtt.py * Update discovery.py * Update discovery.py * Update discovery.py * Update interface.py * Update mqtt.py * Update mqtt.py * Update services.py * Update discovery.py * Update discovery.py * Update mqtt.py * Update discovery.py * Update services.py * Update discovery.py * Update discovery.py * Update mqtt.py * Update discovery.py * fix aiohttp * test * Update const.py * Update addon.py * Update homeassistant.py * Update const.py * Update addon.py * Update homeassistant.py * Update addon.py * Update security.py * Update const.py * Update validate.py * Update const.py * Update addon.py * Update API.md * Update addons.py * Update addon.py * Update validate.py * Update security.py * Update security.py * Update const.py * Update services.py * Update discovery.py * Update API.md * Update services.py * Update API.md * Update services.py * Update discovery.py * Update discovery.py * Update mqtt.py * Update discovery.py * Update discovery.py * Update __init__.py * Update mqtt.py * Update security.py * fix lint * Update core.py * Update API.md * Update services.py
2018-02-08 17:19:47 +01:00
def _register_mounts(self) -> None:
"""Register mounts endpoints."""
api_mounts = APIMounts()
api_mounts.coresys = self.coresys
self.webapp.add_routes(
[
web.get("/mounts", api_mounts.info),
web.post("/mounts", api_mounts.create_mount),
web.put("/mounts/{mount}", api_mounts.update_mount),
web.delete("/mounts/{mount}", api_mounts.delete_mount),
web.post("/mounts/{mount}/reload", api_mounts.reload_mount),
]
)
2021-02-25 16:15:51 +01:00
def _register_store(self) -> None:
"""Register store endpoints."""
api_store = APIStore()
api_store.coresys = self.coresys
self.webapp.add_routes(
[
web.get("/store", api_store.store_info),
web.get("/store/addons", api_store.addons_list),
web.get("/store/addons/{addon}", api_store.addons_addon_info),
web.get("/store/addons/{addon}/{version}", api_store.addons_addon_info),
web.get("/store/addons/{addon}/icon", api_store.addons_addon_icon),
web.get("/store/addons/{addon}/logo", api_store.addons_addon_logo),
web.get(
"/store/addons/{addon}/changelog", api_store.addons_addon_changelog
),
web.get(
"/store/addons/{addon}/documentation",
api_store.addons_addon_documentation,
),
2021-02-25 16:15:51 +01:00
web.post(
"/store/addons/{addon}/install", api_store.addons_addon_install
),
web.post(
"/store/addons/{addon}/install/{version}",
api_store.addons_addon_install,
),
web.post("/store/addons/{addon}/update", api_store.addons_addon_update),
web.post(
"/store/addons/{addon}/update/{version}",
api_store.addons_addon_update,
),
web.post("/store/reload", api_store.reload),
web.get("/store/repositories", api_store.repositories_list),
web.get(
"/store/repositories/{repository}",
api_store.repositories_repository_info,
),
web.post("/store/repositories", api_store.add_repository),
web.delete(
"/store/repositories/{repository}", api_store.remove_repository
),
2021-02-25 16:15:51 +01:00
]
)
# Reroute from legacy
self.webapp.add_routes(
[
web.post("/addons/reload", api_store.reload),
2021-02-25 16:15:51 +01:00
web.post("/addons/{addon}/install", api_store.addons_addon_install),
web.post("/addons/{addon}/update", api_store.addons_addon_update),
web.get("/addons/{addon}/icon", api_store.addons_addon_icon),
web.get("/addons/{addon}/logo", api_store.addons_addon_logo),
web.get("/addons/{addon}/changelog", api_store.addons_addon_changelog),
web.get(
"/addons/{addon}/documentation",
api_store.addons_addon_documentation,
),
2021-02-25 16:15:51 +01:00
]
)
def _register_panel(self) -> None:
"""Register panel for Home Assistant."""
panel_dir = Path(__file__).parent.joinpath("panel")
2019-05-27 12:35:06 +02:00
self.webapp.add_routes([web.static("/app", panel_dir)])
def _register_docker(self) -> None:
"""Register docker configuration functions."""
api_docker = APIDocker()
api_docker.coresys = self.coresys
self.webapp.add_routes(
[
2020-10-06 11:26:56 +02:00
web.get("/docker/info", api_docker.info),
web.get("/docker/registries", api_docker.registries),
web.post("/docker/registries", api_docker.create_registry),
web.delete("/docker/registries/{hostname}", api_docker.remove_registry),
]
)
async def start(self) -> None:
"""Run RESTful API webserver."""
await self._runner.setup()
self._site = web.TCPSite(
2019-05-27 12:35:06 +02:00
self._runner, host="0.0.0.0", port=80, shutdown_timeout=5
)
2017-03-30 16:01:52 +02:00
try:
await self._site.start()
2017-03-30 16:01:52 +02:00
except OSError as err:
_LOGGER.critical("Failed to create HTTP server at 0.0.0.0:80 -> %s", err)
else:
_LOGGER.info("Starting API on %s", self.sys_docker.network.supervisor)
2017-03-30 16:01:52 +02:00
async def stop(self) -> None:
"""Stop RESTful API webserver."""
if not self._site:
return
# Shutdown running API
await self._site.stop()
await self._runner.cleanup()
_LOGGER.info("Stopping API on %s", self.sys_docker.network.supervisor)