From 2de1d35dd1ffa22c16a49dbbfe6bb5d89cb3bd91 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Sat, 28 Mar 2020 15:56:57 +0100 Subject: [PATCH] Get host dmesg as host logs (#1606) * Get host dmesg as host logs * fix lint --- API.md | 4 ++++ supervisor/api/__init__.py | 1 + supervisor/api/host.py | 28 ++++++++++++++++++---------- supervisor/host/info.py | 23 ++++++++++++++++++++++- 4 files changed, 45 insertions(+), 11 deletions(-) diff --git a/API.md b/API.md index eb8bd0bac..b1eb768b5 100644 --- a/API.md +++ b/API.md @@ -252,6 +252,10 @@ return: } ``` +- GET `/host/logs` + +Return host dmesg + - POST `/host/options` ```json diff --git a/supervisor/api/__init__.py b/supervisor/api/__init__.py index 846f2ff2f..e405f88e6 100644 --- a/supervisor/api/__init__.py +++ b/supervisor/api/__init__.py @@ -74,6 +74,7 @@ class RestAPI(CoreSysAttributes): self.webapp.add_routes( [ web.get("/host/info", api_host.info), + web.get("/host/logs", api_host.logs), web.post("/host/reboot", api_host.reboot), web.post("/host/shutdown", api_host.shutdown), web.post("/host/reload", api_host.reload), diff --git a/supervisor/api/host.py b/supervisor/api/host.py index d686863c5..2e2361164 100644 --- a/supervisor/api/host.py +++ b/supervisor/api/host.py @@ -1,24 +1,27 @@ """Init file for Supervisor host RESTful API.""" import asyncio import logging +from typing import Awaitable +from aiohttp import web import voluptuous as vol -from .utils import api_process, api_validate from ..const import ( - ATTR_HOSTNAME, - ATTR_FEATURES, - ATTR_KERNEL, - ATTR_OPERATING_SYSTEM, ATTR_CHASSIS, - ATTR_DEPLOYMENT, - ATTR_STATE, - ATTR_NAME, - ATTR_DESCRIPTON, - ATTR_SERVICES, ATTR_CPE, + ATTR_DEPLOYMENT, + ATTR_DESCRIPTON, + ATTR_FEATURES, + ATTR_HOSTNAME, + ATTR_KERNEL, + ATTR_NAME, + ATTR_OPERATING_SYSTEM, + ATTR_SERVICES, + ATTR_STATE, + CONTENT_TYPE_BINARY, ) from ..coresys import CoreSysAttributes +from .utils import api_process, api_process_raw, api_validate _LOGGER: logging.Logger = logging.getLogger(__name__) @@ -107,3 +110,8 @@ class APIHost(CoreSysAttributes): """Restart a service.""" unit = request.match_info.get(SERVICE) return asyncio.shield(self.sys_host.services.restart(unit)) + + @api_process_raw(CONTENT_TYPE_BINARY) + def logs(self, request: web.Request) -> Awaitable[bytes]: + """Return host kernel logs.""" + return self.sys_host.info.get_dmesg() diff --git a/supervisor/host/info.py b/supervisor/host/info.py index cc964e899..58a1ee544 100644 --- a/supervisor/host/info.py +++ b/supervisor/host/info.py @@ -1,9 +1,15 @@ """Info control for host.""" +import asyncio import logging from typing import Optional from ..coresys import CoreSysAttributes -from ..exceptions import HostNotSupportedError, DBusNotConnectedError, DBusError +from ..exceptions import ( + HostNotSupportedError, + HostError, + DBusNotConnectedError, + DBusError, +) _LOGGER: logging.Logger = logging.getLogger(__name__) @@ -45,6 +51,21 @@ class InfoCenter(CoreSysAttributes): """Return local CPE.""" return self.sys_dbus.hostname.cpe + async def get_dmesg(self) -> bytes: + """Return host dmesg output.""" + proc = await asyncio.create_subprocess_shell( + "dmesg", stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.STDOUT + ) + + # Get kernel log + try: + stdout, _ = await proc.communicate() + except OSError as err: + _LOGGER.error("Can't read kernel log: %s", err) + raise HostError() + + return stdout + async def update(self): """Update properties over dbus.""" _LOGGER.info("Update local host information")