summaryrefslogtreecommitdiff
path: root/kvmd/apps
diff options
context:
space:
mode:
authorMaxim Devaev <[email protected]>2022-04-06 00:39:16 +0300
committerMaxim Devaev <[email protected]>2022-04-06 00:55:20 +0300
commit6f6772a6b62ecaaa166197f097f82d81c6fb9422 (patch)
treeb0e1a2d8e316e8e7abe9b51f702ac7d8d27aedfa /kvmd/apps
parent8ce08fb4567ed7f3cfad85da4ae1e123eef42024 (diff)
refactoring
Diffstat (limited to 'kvmd/apps')
-rw-r--r--kvmd/apps/kvmd/api/atx.py6
-rw-r--r--kvmd/apps/kvmd/api/auth.py14
-rw-r--r--kvmd/apps/kvmd/api/export.py4
-rw-r--r--kvmd/apps/kvmd/api/hid.py14
-rw-r--r--kvmd/apps/kvmd/api/info.py6
-rw-r--r--kvmd/apps/kvmd/api/log.py6
-rw-r--r--kvmd/apps/kvmd/api/msd.py14
-rw-r--r--kvmd/apps/kvmd/api/redfish.py8
-rw-r--r--kvmd/apps/kvmd/api/streamer.py8
-rw-r--r--kvmd/apps/kvmd/api/ugpio.py6
-rw-r--r--kvmd/apps/kvmd/auth.py4
-rw-r--r--kvmd/apps/kvmd/http.py264
-rw-r--r--kvmd/apps/kvmd/server.py27
-rw-r--r--kvmd/apps/kvmd/snapshoter.py4
-rw-r--r--kvmd/apps/kvmd/ugpio.py10
15 files changed, 65 insertions, 330 deletions
diff --git a/kvmd/apps/kvmd/api/atx.py b/kvmd/apps/kvmd/api/atx.py
index 9107b9c6..68ce0479 100644
--- a/kvmd/apps/kvmd/api/atx.py
+++ b/kvmd/apps/kvmd/api/atx.py
@@ -23,15 +23,15 @@
from aiohttp.web import Request
from aiohttp.web import Response
+from ....htserver import exposed_http
+from ....htserver import make_json_response
+
from ....plugins.atx import BaseAtx
from ....validators.basic import valid_bool
from ....validators.kvm import valid_atx_power_action
from ....validators.kvm import valid_atx_button
-from ..http import exposed_http
-from ..http import make_json_response
-
# =====
class AtxApi:
diff --git a/kvmd/apps/kvmd/api/auth.py b/kvmd/apps/kvmd/api/auth.py
index 36604b2e..590f1411 100644
--- a/kvmd/apps/kvmd/api/auth.py
+++ b/kvmd/apps/kvmd/api/auth.py
@@ -25,17 +25,17 @@ import base64
from aiohttp.web import Request
from aiohttp.web import Response
+from ....htserver import UnauthorizedError
+from ....htserver import ForbiddenError
+from ....htserver import HttpExposed
+from ....htserver import exposed_http
+from ....htserver import make_json_response
+from ....htserver import set_request_auth_info
+
from ....validators.auth import valid_user
from ....validators.auth import valid_passwd
from ....validators.auth import valid_auth_token
-from ..http import UnauthorizedError
-from ..http import ForbiddenError
-from ..http import HttpExposed
-from ..http import exposed_http
-from ..http import make_json_response
-from ..http import set_request_auth_info
-
from ..auth import AuthManager
diff --git a/kvmd/apps/kvmd/api/export.py b/kvmd/apps/kvmd/api/export.py
index 91031056..ca367f30 100644
--- a/kvmd/apps/kvmd/api/export.py
+++ b/kvmd/apps/kvmd/api/export.py
@@ -30,14 +30,14 @@ from aiohttp.web import Response
from .... import tools
+from ....htserver import exposed_http
+
from ....plugins.atx import BaseAtx
from ....plugins.ugpio import UserGpioModes
from ..info import InfoManager
from ..ugpio import UserGpio
-from ..http import exposed_http
-
# =====
class ExportApi:
diff --git a/kvmd/apps/kvmd/api/hid.py b/kvmd/apps/kvmd/api/hid.py
index 7f344e43..ddbaadd8 100644
--- a/kvmd/apps/kvmd/api/hid.py
+++ b/kvmd/apps/kvmd/api/hid.py
@@ -36,6 +36,13 @@ from aiohttp.web import WebSocketResponse
from ....mouse import MouseRange
+from ....keyboard.keysym import build_symmap
+from ....keyboard.printer import text_to_web_keys
+
+from ....htserver import exposed_http
+from ....htserver import exposed_ws
+from ....htserver import make_json_response
+
from ....plugins.hid import BaseHid
from ....validators import raise_error
@@ -49,13 +56,6 @@ from ....validators.hid import valid_hid_mouse_move
from ....validators.hid import valid_hid_mouse_button
from ....validators.hid import valid_hid_mouse_delta
-from ....keyboard.keysym import build_symmap
-from ....keyboard.printer import text_to_web_keys
-
-from ..http import exposed_http
-from ..http import exposed_ws
-from ..http import make_json_response
-
# =====
class HidApi:
diff --git a/kvmd/apps/kvmd/api/info.py b/kvmd/apps/kvmd/api/info.py
index 55876a1f..bb7caf79 100644
--- a/kvmd/apps/kvmd/api/info.py
+++ b/kvmd/apps/kvmd/api/info.py
@@ -27,13 +27,13 @@ from typing import List
from aiohttp.web import Request
from aiohttp.web import Response
+from ....htserver import exposed_http
+from ....htserver import make_json_response
+
from ....validators.kvm import valid_info_fields
from ..info import InfoManager
-from ..http import exposed_http
-from ..http import make_json_response
-
# =====
class InfoApi:
diff --git a/kvmd/apps/kvmd/api/log.py b/kvmd/apps/kvmd/api/log.py
index b6e67296..dd95aa4f 100644
--- a/kvmd/apps/kvmd/api/log.py
+++ b/kvmd/apps/kvmd/api/log.py
@@ -23,14 +23,14 @@
from aiohttp.web import Request
from aiohttp.web import StreamResponse
+from ....htserver import exposed_http
+from ....htserver import start_streaming
+
from ....validators.basic import valid_bool
from ....validators.kvm import valid_log_seek
from ..logreader import LogReader
-from ..http import exposed_http
-from ..http import start_streaming
-
# =====
class LogApi:
diff --git a/kvmd/apps/kvmd/api/msd.py b/kvmd/apps/kvmd/api/msd.py
index 8b1769b5..75852dd7 100644
--- a/kvmd/apps/kvmd/api/msd.py
+++ b/kvmd/apps/kvmd/api/msd.py
@@ -36,6 +36,13 @@ from ....logging import get_logger
from .... import htclient
+from ....htserver import exposed_http
+from ....htserver import make_json_response
+from ....htserver import make_json_exception
+from ....htserver import start_streaming
+from ....htserver import stream_json
+from ....htserver import stream_json_exception
+
from ....plugins.msd import BaseMsd
from ....validators.basic import valid_bool
@@ -44,13 +51,6 @@ from ....validators.basic import valid_float_f01
from ....validators.net import valid_url
from ....validators.kvm import valid_msd_image_name
-from ..http import exposed_http
-from ..http import make_json_response
-from ..http import make_json_exception
-from ..http import start_streaming
-from ..http import stream_json
-from ..http import stream_json_exception
-
# ======
class MsdApi:
diff --git a/kvmd/apps/kvmd/api/redfish.py b/kvmd/apps/kvmd/api/redfish.py
index 5afd5110..c740ca55 100644
--- a/kvmd/apps/kvmd/api/redfish.py
+++ b/kvmd/apps/kvmd/api/redfish.py
@@ -25,6 +25,10 @@ import asyncio
from aiohttp.web import Request
from aiohttp.web import Response
+from ....htserver import HttpError
+from ....htserver import exposed_http
+from ....htserver import make_json_response
+
from ....plugins.atx import BaseAtx
from ....validators import ValidatorError
@@ -32,10 +36,6 @@ from ....validators import check_string_in_list
from ..info import InfoManager
-from ..http import HttpError
-from ..http import exposed_http
-from ..http import make_json_response
-
# =====
class RedfishApi:
diff --git a/kvmd/apps/kvmd/api/streamer.py b/kvmd/apps/kvmd/api/streamer.py
index a2cf961d..0cadb141 100644
--- a/kvmd/apps/kvmd/api/streamer.py
+++ b/kvmd/apps/kvmd/api/streamer.py
@@ -26,6 +26,10 @@ from typing import Dict
from aiohttp.web import Request
from aiohttp.web import Response
+from ....htserver import UnavailableError
+from ....htserver import exposed_http
+from ....htserver import make_json_response
+
from ....validators import check_string_in_list
from ....validators.basic import valid_bool
from ....validators.basic import valid_number
@@ -33,10 +37,6 @@ from ....validators.basic import valid_int_f0
from ....validators.basic import valid_string_list
from ....validators.kvm import valid_stream_quality
-from ..http import UnavailableError
-from ..http import exposed_http
-from ..http import make_json_response
-
from ..streamer import Streamer
from ..tesseract import TesseractOcr
diff --git a/kvmd/apps/kvmd/api/ugpio.py b/kvmd/apps/kvmd/api/ugpio.py
index d5d127cc..b41fba73 100644
--- a/kvmd/apps/kvmd/api/ugpio.py
+++ b/kvmd/apps/kvmd/api/ugpio.py
@@ -23,15 +23,15 @@
from aiohttp.web import Request
from aiohttp.web import Response
+from ....htserver import exposed_http
+from ....htserver import make_json_response
+
from ....validators.basic import valid_bool
from ....validators.basic import valid_float_f0
from ....validators.ugpio import valid_ugpio_channel
from ..ugpio import UserGpio
-from ..http import exposed_http
-from ..http import make_json_response
-
# =====
class UserGpioApi:
diff --git a/kvmd/apps/kvmd/auth.py b/kvmd/apps/kvmd/auth.py
index b9933181..8bd2286d 100644
--- a/kvmd/apps/kvmd/auth.py
+++ b/kvmd/apps/kvmd/auth.py
@@ -28,11 +28,11 @@ from typing import Optional
from ...logging import get_logger
+from ... import aiotools
+
from ...plugins.auth import BaseAuthService
from ...plugins.auth import get_auth_service_class
-from ... import aiotools
-
# =====
class AuthManager:
diff --git a/kvmd/apps/kvmd/http.py b/kvmd/apps/kvmd/http.py
deleted file mode 100644
index a057caed..00000000
--- a/kvmd/apps/kvmd/http.py
+++ /dev/null
@@ -1,264 +0,0 @@
-# ========================================================================== #
-# #
-# KVMD - The main PiKVM daemon. #
-# #
-# Copyright (C) 2018-2022 Maxim Devaev <[email protected]> #
-# #
-# This program is free software: you can redistribute it and/or modify #
-# it under the terms of the GNU General Public License as published by #
-# the Free Software Foundation, either version 3 of the License, or #
-# (at your option) any later version. #
-# #
-# This program is distributed in the hope that it will be useful, #
-# but WITHOUT ANY WARRANTY; without even the implied warranty of #
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
-# GNU General Public License for more details. #
-# #
-# You should have received a copy of the GNU General Public License #
-# along with this program. If not, see <https://www.gnu.org/licenses/>. #
-# #
-# ========================================================================== #
-
-
-import os
-import socket
-import asyncio
-import dataclasses
-import inspect
-import json
-
-from typing import List
-from typing import Dict
-from typing import Callable
-from typing import Optional
-
-from aiohttp.web import BaseRequest
-from aiohttp.web import Request
-from aiohttp.web import Response
-from aiohttp.web import StreamResponse
-from aiohttp.web import Application
-from aiohttp.web import run_app
-from aiohttp.web import normalize_path_middleware
-
-try:
- from aiohttp.web import AccessLogger # type: ignore
-except ImportError:
- from aiohttp.helpers import AccessLogger # type: ignore
-
-from ...logging import get_logger
-
-
-# =====
-class HttpError(Exception):
- def __init__(self, msg: str, status: int) -> None:
- super().__init__(msg)
- self.status = status
-
-
-class UnauthorizedError(HttpError):
- def __init__(self) -> None:
- super().__init__("Unauthorized", 401)
-
-
-class ForbiddenError(HttpError):
- def __init__(self) -> None:
- super().__init__("Forbidden", 403)
-
-
-class UnavailableError(HttpError):
- def __init__(self) -> None:
- super().__init__("Service Unavailable", 503)
-
-
-# =====
[email protected](frozen=True)
-class HttpExposed:
- method: str
- path: str
- auth_required: bool
- handler: Callable
-
-
-_HTTP_EXPOSED = "_http_exposed"
-_HTTP_METHOD = "_http_method"
-_HTTP_PATH = "_http_path"
-_HTTP_AUTH_REQUIRED = "_http_auth_required"
-
-
-def exposed_http(http_method: str, path: str, auth_required: bool=True) -> Callable:
- def set_attrs(handler: Callable) -> Callable:
- setattr(handler, _HTTP_EXPOSED, True)
- setattr(handler, _HTTP_METHOD, http_method)
- setattr(handler, _HTTP_PATH, path)
- setattr(handler, _HTTP_AUTH_REQUIRED, auth_required)
- return handler
- return set_attrs
-
-
-def get_exposed_http(obj: object) -> List[HttpExposed]:
- return [
- HttpExposed(
- method=getattr(handler, _HTTP_METHOD),
- path=getattr(handler, _HTTP_PATH),
- auth_required=getattr(handler, _HTTP_AUTH_REQUIRED),
- handler=handler,
- )
- for handler in [getattr(obj, name) for name in dir(obj)]
- if inspect.ismethod(handler) and getattr(handler, _HTTP_EXPOSED, False)
- ]
-
-
-# =====
[email protected](frozen=True)
-class WsExposed:
- event_type: str
- handler: Callable
-
-
-_WS_EXPOSED = "_ws_exposed"
-_WS_EVENT_TYPE = "_ws_event_type"
-
-
-def exposed_ws(event_type: str) -> Callable:
- def set_attrs(handler: Callable) -> Callable:
- setattr(handler, _WS_EXPOSED, True)
- setattr(handler, _WS_EVENT_TYPE, event_type)
- return handler
- return set_attrs
-
-
-def get_exposed_ws(obj: object) -> List[WsExposed]:
- return [
- WsExposed(
- event_type=getattr(handler, _WS_EVENT_TYPE),
- handler=handler,
- )
- for handler in [getattr(obj, name) for name in dir(obj)]
- if inspect.ismethod(handler) and getattr(handler, _WS_EXPOSED, False)
- ]
-
-
-# =====
-def make_json_response(
- result: Optional[Dict]=None,
- status: int=200,
- set_cookies: Optional[Dict[str, str]]=None,
- wrap_result: bool=True,
-) -> Response:
-
- response = Response(
- text=json.dumps(({
- "ok": (status == 200),
- "result": (result or {}),
- } if wrap_result else result), sort_keys=True, indent=4),
- status=status,
- content_type="application/json",
- )
- if set_cookies:
- for (key, value) in set_cookies.items():
- response.set_cookie(key, value)
- return response
-
-
-def make_json_exception(err: Exception, status: Optional[int]=None) -> Response:
- name = type(err).__name__
- msg = str(err)
- if isinstance(err, HttpError):
- status = err.status
- else:
- get_logger().error("API error: %s: %s", name, msg)
- assert status is not None, err
- return make_json_response({
- "error": name,
- "error_msg": msg,
- }, status=status)
-
-
-async def start_streaming(request: Request, content_type: str="application/x-ndjson") -> StreamResponse:
- response = StreamResponse(status=200, reason="OK", headers={"Content-Type": content_type})
- await response.prepare(request)
- return response
-
-
-async def stream_json(response: StreamResponse, result: Dict, ok: bool=True) -> None:
- await response.write(json.dumps({
- "ok": ok,
- "result": result,
- }).encode("utf-8") + b"\r\n")
-
-
-async def stream_json_exception(response: StreamResponse, err: Exception) -> None:
- name = type(err).__name__
- msg = str(err)
- get_logger().error("API error: %s: %s", name, msg)
- await stream_json(response, {
- "error": name,
- "error_msg": msg,
- }, False)
-
-
-# =====
-_REQUEST_AUTH_INFO = "_kvmd_auth_info"
-
-
-def _format_P(request: BaseRequest, *_, **__) -> str: # type: ignore # pylint: disable=invalid-name
- return (getattr(request, _REQUEST_AUTH_INFO, None) or "-")
-
-
-AccessLogger._format_P = staticmethod(_format_P) # type: ignore # pylint: disable=protected-access
-
-
-def set_request_auth_info(request: BaseRequest, info: str) -> None:
- setattr(request, _REQUEST_AUTH_INFO, info)
-
-
-# =====
-class HttpServer:
- def run(
- self,
- unix_path: str,
- unix_rm: bool,
- unix_mode: int,
- access_log_format: str,
- ) -> None:
-
- if unix_rm and os.path.exists(unix_path):
- os.remove(unix_path)
- server_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
- server_socket.bind(unix_path)
- if unix_mode:
- os.chmod(unix_path, unix_mode)
-
- run_app(
- sock=server_socket,
- app=self.__make_app(),
- shutdown_timeout=1,
- access_log_format=access_log_format,
- print=self.__run_app_print,
- loop=asyncio.get_event_loop(),
- )
-
- async def _init_app(self, app: Application) -> None:
- raise NotImplementedError
-
- async def _on_shutdown(self, app: Application) -> None:
- _ = app
-
- async def _on_cleanup(self, app: Application) -> None:
- _ = app
-
- async def __make_app(self) -> Application:
- app = Application(middlewares=[normalize_path_middleware(
- append_slash=False,
- remove_slash=True,
- merge_slashes=True,
- )])
- app.on_shutdown.append(self._on_shutdown)
- app.on_cleanup.append(self._on_cleanup)
- await self._init_app(app)
- return app
-
- def __run_app_print(self, text: str) -> None:
- logger = get_logger(0)
- for line in text.strip().splitlines():
- logger.info(line.strip())
diff --git a/kvmd/apps/kvmd/server.py b/kvmd/apps/kvmd/server.py
index a69cff00..f33412d9 100644
--- a/kvmd/apps/kvmd/server.py
+++ b/kvmd/apps/kvmd/server.py
@@ -45,8 +45,20 @@ from ...logging import get_logger
from ...errors import OperationError
from ...errors import IsBusyError
-from ...plugins import BasePlugin
+from ... import aiotools
+from ... import aioproc
+from ...htserver import HttpError
+from ...htserver import HttpExposed
+from ...htserver import exposed_http
+from ...htserver import exposed_ws
+from ...htserver import get_exposed_http
+from ...htserver import get_exposed_ws
+from ...htserver import make_json_response
+from ...htserver import make_json_exception
+from ...htserver import HttpServer
+
+from ...plugins import BasePlugin
from ...plugins.hid import BaseHid
from ...plugins.atx import BaseAtx
from ...plugins.msd import BaseMsd
@@ -59,9 +71,6 @@ from ...validators.kvm import valid_stream_resolution
from ...validators.kvm import valid_stream_h264_bitrate
from ...validators.kvm import valid_stream_h264_gop
-from ... import aiotools
-from ... import aioproc
-
from .auth import AuthManager
from .info import InfoManager
from .logreader import LogReader
@@ -70,16 +79,6 @@ from .streamer import Streamer
from .snapshoter import Snapshoter
from .tesseract import TesseractOcr
-from .http import HttpError
-from .http import HttpExposed
-from .http import exposed_http
-from .http import exposed_ws
-from .http import get_exposed_http
-from .http import get_exposed_ws
-from .http import make_json_response
-from .http import make_json_exception
-from .http import HttpServer
-
from .api.auth import AuthApi
from .api.auth import check_request_auth
diff --git a/kvmd/apps/kvmd/snapshoter.py b/kvmd/apps/kvmd/snapshoter.py
index 380984af..65c59eaa 100644
--- a/kvmd/apps/kvmd/snapshoter.py
+++ b/kvmd/apps/kvmd/snapshoter.py
@@ -27,10 +27,10 @@ from typing import Callable
from ...logging import get_logger
-from ...plugins.hid import BaseHid
-
from ... import aiotools
+from ...plugins.hid import BaseHid
+
from .streamer import Streamer
diff --git a/kvmd/apps/kvmd/ugpio.py b/kvmd/apps/kvmd/ugpio.py
index 458710dc..de69cacf 100644
--- a/kvmd/apps/kvmd/ugpio.py
+++ b/kvmd/apps/kvmd/ugpio.py
@@ -31,6 +31,11 @@ from typing import Any
from ...logging import get_logger
+from ...errors import IsBusyError
+
+from ... import tools
+from ... import aiotools
+
from ...plugins.ugpio import GpioError
from ...plugins.ugpio import GpioOperationError
from ...plugins.ugpio import GpioDriverOfflineError
@@ -38,13 +43,8 @@ from ...plugins.ugpio import UserGpioModes
from ...plugins.ugpio import BaseUserGpioDriver
from ...plugins.ugpio import get_ugpio_driver_class
-from ... import tools
-from ... import aiotools
-
from ...yamlconf import Section
-from ...errors import IsBusyError
-
# =====
class GpioChannelNotFoundError(GpioOperationError):