mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2025-12-12 09:10:30 +08:00
complex info handle
This commit is contained in:
parent
53eb74670d
commit
5f1733d002
@ -216,17 +216,16 @@ def _get_config_scheme() -> Dict:
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
"info": { # Accessed via global config, see kvmd/info.py for details
|
"info": { # Accessed via global config, see kvmd/info for details
|
||||||
"meta": Option("/etc/kvmd/meta.yaml", type=valid_abs_file),
|
"meta": Option("/etc/kvmd/meta.yaml", type=valid_abs_file),
|
||||||
"extras": Option("/usr/share/kvmd/extras", type=valid_abs_dir),
|
"extras": Option("/usr/share/kvmd/extras", type=valid_abs_dir),
|
||||||
},
|
|
||||||
|
|
||||||
"hw": {
|
"hw": {
|
||||||
"vcgencmd_cmd": Option(["/opt/vc/bin/vcgencmd"], type=valid_command),
|
"vcgencmd_cmd": Option(["/opt/vc/bin/vcgencmd"], type=valid_command),
|
||||||
"procfs_prefix": Option("", type=(lambda arg: str(arg).strip())),
|
"procfs_prefix": Option("", type=(lambda arg: str(arg).strip())),
|
||||||
"sysfs_prefix": Option("", type=(lambda arg: str(arg).strip())),
|
"sysfs_prefix": Option("", type=(lambda arg: str(arg).strip())),
|
||||||
"state_poll": Option(10.0, type=valid_float_f01),
|
"state_poll": Option(10.0, type=valid_float_f01),
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
|
||||||
"wol": {
|
"wol": {
|
||||||
"ip": Option("255.255.255.255", type=(lambda arg: valid_ip(arg, v6=False))),
|
"ip": Option("255.255.255.255", type=(lambda arg: valid_ip(arg, v6=False))),
|
||||||
|
|||||||
@ -35,7 +35,6 @@ from .. import init
|
|||||||
|
|
||||||
from .auth import AuthManager
|
from .auth import AuthManager
|
||||||
from .info import InfoManager
|
from .info import InfoManager
|
||||||
from .hw import HwManager
|
|
||||||
from .logreader import LogReader
|
from .logreader import LogReader
|
||||||
from .wol import WakeOnLan
|
from .wol import WakeOnLan
|
||||||
from .streamer import Streamer
|
from .streamer import Streamer
|
||||||
@ -78,7 +77,6 @@ def main(argv: Optional[List[str]]=None) -> None:
|
|||||||
enabled=config.auth.enabled,
|
enabled=config.auth.enabled,
|
||||||
),
|
),
|
||||||
info_manager=InfoManager(global_config),
|
info_manager=InfoManager(global_config),
|
||||||
hw_manager=HwManager(**config.hw._unpack()),
|
|
||||||
log_reader=LogReader(),
|
log_reader=LogReader(),
|
||||||
wol=WakeOnLan(**config.wol._unpack()),
|
wol=WakeOnLan(**config.wol._unpack()),
|
||||||
|
|
||||||
|
|||||||
@ -20,9 +20,16 @@
|
|||||||
# ========================================================================== #
|
# ========================================================================== #
|
||||||
|
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
|
||||||
|
from typing import List
|
||||||
|
|
||||||
from aiohttp.web import Request
|
from aiohttp.web import Request
|
||||||
from aiohttp.web import Response
|
from aiohttp.web import Response
|
||||||
|
|
||||||
|
from ....validators import check_string_in_list
|
||||||
|
from ....validators.basic import valid_string_list
|
||||||
|
|
||||||
from ..info import InfoManager
|
from ..info import InfoManager
|
||||||
|
|
||||||
from ..http import exposed_http
|
from ..http import exposed_http
|
||||||
@ -37,5 +44,18 @@ class InfoApi:
|
|||||||
# =====
|
# =====
|
||||||
|
|
||||||
@exposed_http("GET", "/info")
|
@exposed_http("GET", "/info")
|
||||||
async def __state_handler(self, _: Request) -> Response:
|
async def __common_state_handler(self, request: Request) -> Response:
|
||||||
return make_json_response(await self.__info_manager.get_state())
|
fields = self.__valid_info_fields(request)
|
||||||
|
results = dict(zip(fields, await asyncio.gather(*[
|
||||||
|
self.__info_manager.get_submanager(field).get_state()
|
||||||
|
for field in fields
|
||||||
|
])))
|
||||||
|
return make_json_response(results)
|
||||||
|
|
||||||
|
def __valid_info_fields(self, request: Request) -> List[str]:
|
||||||
|
subs = self.__info_manager.get_subs()
|
||||||
|
return (sorted(set(valid_string_list(
|
||||||
|
arg=request.query.get("fields", ",".join(subs)),
|
||||||
|
subval=(lambda field: check_string_in_list(field, "info field", subs)),
|
||||||
|
name="info fields list",
|
||||||
|
))) or subs)
|
||||||
|
|||||||
48
kvmd/apps/kvmd/info/__init__.py
Normal file
48
kvmd/apps/kvmd/info/__init__.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# ========================================================================== #
|
||||||
|
# #
|
||||||
|
# KVMD - The main Pi-KVM daemon. #
|
||||||
|
# #
|
||||||
|
# Copyright (C) 2018 Maxim Devaev <mdevaev@gmail.com> #
|
||||||
|
# #
|
||||||
|
# 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/>. #
|
||||||
|
# #
|
||||||
|
# ========================================================================== #
|
||||||
|
|
||||||
|
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from ....yamlconf import Section
|
||||||
|
|
||||||
|
from .base import BaseInfoSubmanager
|
||||||
|
from .system import SystemInfoSubmanager
|
||||||
|
from .meta import MetaInfoSubmanager
|
||||||
|
from .extras import ExtrasInfoSubmanager
|
||||||
|
from .hw import HwInfoSubmanager
|
||||||
|
|
||||||
|
|
||||||
|
# =====
|
||||||
|
class InfoManager:
|
||||||
|
def __init__(self, config: Section) -> None:
|
||||||
|
self.__subs = {
|
||||||
|
"system": SystemInfoSubmanager(config.kvmd.streamer.cmd),
|
||||||
|
"meta": MetaInfoSubmanager(config.kvmd.info.meta),
|
||||||
|
"extras": ExtrasInfoSubmanager(config),
|
||||||
|
"hw": HwInfoSubmanager(**config.kvmd.info.hw._unpack()),
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_subs(self) -> List[str]:
|
||||||
|
return list(self.__subs)
|
||||||
|
|
||||||
|
def get_submanager(self, name: str) -> BaseInfoSubmanager:
|
||||||
|
return self.__subs[name]
|
||||||
@ -20,22 +20,11 @@
|
|||||||
# ========================================================================== #
|
# ========================================================================== #
|
||||||
|
|
||||||
|
|
||||||
from aiohttp.web import Request
|
from typing import Dict
|
||||||
from aiohttp.web import Response
|
from typing import Optional
|
||||||
|
|
||||||
from ..hw import HwManager
|
|
||||||
|
|
||||||
from ..http import exposed_http
|
|
||||||
from ..http import make_json_response
|
|
||||||
|
|
||||||
|
|
||||||
# =====
|
# =====
|
||||||
class HwApi:
|
class BaseInfoSubmanager:
|
||||||
def __init__(self, hw_manager: HwManager) -> None:
|
async def get_state(self) -> Optional[Dict]:
|
||||||
self.__hw_manager = hw_manager
|
raise NotImplementedError
|
||||||
|
|
||||||
# =====
|
|
||||||
|
|
||||||
@exposed_http("GET", "/hw")
|
|
||||||
async def __state_handler(self, _: Request) -> Response:
|
|
||||||
return make_json_response(await self.__hw_manager.get_state())
|
|
||||||
@ -21,8 +21,6 @@
|
|||||||
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import asyncio
|
|
||||||
import platform
|
|
||||||
import contextlib
|
import contextlib
|
||||||
|
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
@ -31,81 +29,27 @@ from typing import Optional
|
|||||||
import dbus # pylint: disable=import-error
|
import dbus # pylint: disable=import-error
|
||||||
import dbus.exceptions
|
import dbus.exceptions
|
||||||
|
|
||||||
from ...logging import get_logger
|
from ....logging import get_logger
|
||||||
|
|
||||||
from ...yamlconf import Section
|
from ....yamlconf import Section
|
||||||
from ...yamlconf.loader import load_yaml_file
|
from ....yamlconf.loader import load_yaml_file
|
||||||
|
|
||||||
from ... import aiotools
|
from .... import aiotools
|
||||||
from ... import aioproc
|
|
||||||
|
|
||||||
from ... import __version__
|
from .base import BaseInfoSubmanager
|
||||||
|
|
||||||
|
|
||||||
# =====
|
# =====
|
||||||
class InfoManager:
|
class ExtrasInfoSubmanager(BaseInfoSubmanager):
|
||||||
def __init__(self, global_config: Section) -> None:
|
def __init__(self, global_config: Section) -> None:
|
||||||
self.__global_config = global_config
|
self.__global_config = global_config
|
||||||
|
|
||||||
async def get_state(self) -> Dict:
|
async def get_state(self) -> Optional[Dict]:
|
||||||
(streamer_info, meta_info, extras_info) = await asyncio.gather(
|
return (await aiotools.run_async(self.__inner_get_state))
|
||||||
self.__get_streamer_info(),
|
|
||||||
self.__get_meta_info(),
|
|
||||||
self.__get_extras_info(),
|
|
||||||
)
|
|
||||||
uname_info = platform.uname() # Uname using the internal cache
|
|
||||||
return {
|
|
||||||
"system": {
|
|
||||||
"kvmd": {"version": __version__},
|
|
||||||
"streamer": streamer_info,
|
|
||||||
"kernel": {
|
|
||||||
field: getattr(uname_info, field)
|
|
||||||
for field in ["system", "release", "version", "machine"]
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"meta": meta_info,
|
|
||||||
"extras": extras_info,
|
|
||||||
}
|
|
||||||
|
|
||||||
# =====
|
# =====
|
||||||
|
|
||||||
async def __get_streamer_info(self) -> Dict:
|
def __inner_get_state(self) -> Optional[Dict]:
|
||||||
version = ""
|
|
||||||
features: Dict[str, bool] = {}
|
|
||||||
try:
|
|
||||||
path = self.__global_config.kvmd.streamer.cmd[0]
|
|
||||||
((_, version), (_, features_text)) = await asyncio.gather(
|
|
||||||
aioproc.read_process([path, "--version"], err_to_null=True),
|
|
||||||
aioproc.read_process([path, "--features"], err_to_null=True),
|
|
||||||
)
|
|
||||||
except Exception:
|
|
||||||
get_logger(0).exception("Can't get streamer info")
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
for line in features_text.split("\n"):
|
|
||||||
(status, name) = map(str.strip, line.split(" "))
|
|
||||||
features[name] = (status == "+")
|
|
||||||
except Exception:
|
|
||||||
get_logger(0).exception("Can't parse streamer features")
|
|
||||||
return {
|
|
||||||
"app": os.path.basename(path),
|
|
||||||
"version": version,
|
|
||||||
"features": features,
|
|
||||||
}
|
|
||||||
|
|
||||||
async def __get_meta_info(self) -> Optional[Dict]:
|
|
||||||
try:
|
|
||||||
return ((await aiotools.run_async(load_yaml_file, self.__global_config.kvmd.info.meta)) or {})
|
|
||||||
except Exception:
|
|
||||||
get_logger(0).exception("Can't parse meta")
|
|
||||||
return None
|
|
||||||
|
|
||||||
async def __get_extras_info(self) -> Optional[Dict]:
|
|
||||||
return (await aiotools.run_async(self.__inner_get_extras_info))
|
|
||||||
|
|
||||||
# =====
|
|
||||||
|
|
||||||
def __inner_get_extras_info(self) -> Optional[Dict]:
|
|
||||||
try:
|
try:
|
||||||
extras_path = self.__global_config.kvmd.info.extras
|
extras_path = self.__global_config.kvmd.info.extras
|
||||||
extras: Dict[str, Dict] = {}
|
extras: Dict[str, Dict] = {}
|
||||||
@ -31,9 +31,11 @@ from typing import Optional
|
|||||||
|
|
||||||
import aiofiles
|
import aiofiles
|
||||||
|
|
||||||
from ...logging import get_logger
|
from ....logging import get_logger
|
||||||
|
|
||||||
from ... import aioproc
|
from .... import aioproc
|
||||||
|
|
||||||
|
from .base import BaseInfoSubmanager
|
||||||
|
|
||||||
|
|
||||||
# =====
|
# =====
|
||||||
@ -41,7 +43,7 @@ _RetvalT = TypeVar("_RetvalT")
|
|||||||
|
|
||||||
|
|
||||||
# =====
|
# =====
|
||||||
class HwManager:
|
class HwInfoSubmanager(BaseInfoSubmanager):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
vcgencmd_cmd: List[str],
|
vcgencmd_cmd: List[str],
|
||||||
45
kvmd/apps/kvmd/info/meta.py
Normal file
45
kvmd/apps/kvmd/info/meta.py
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
# ========================================================================== #
|
||||||
|
# #
|
||||||
|
# KVMD - The main Pi-KVM daemon. #
|
||||||
|
# #
|
||||||
|
# Copyright (C) 2018 Maxim Devaev <mdevaev@gmail.com> #
|
||||||
|
# #
|
||||||
|
# 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/>. #
|
||||||
|
# #
|
||||||
|
# ========================================================================== #
|
||||||
|
|
||||||
|
|
||||||
|
from typing import Dict
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from ....logging import get_logger
|
||||||
|
|
||||||
|
from ....yamlconf.loader import load_yaml_file
|
||||||
|
|
||||||
|
from .... import aiotools
|
||||||
|
|
||||||
|
from .base import BaseInfoSubmanager
|
||||||
|
|
||||||
|
|
||||||
|
# =====
|
||||||
|
class MetaInfoSubmanager(BaseInfoSubmanager):
|
||||||
|
def __init__(self, meta_path: str) -> None:
|
||||||
|
self.__meta_path = meta_path
|
||||||
|
|
||||||
|
async def get_state(self) -> Optional[Dict]:
|
||||||
|
try:
|
||||||
|
return ((await aiotools.run_async(load_yaml_file, self.__meta_path)) or {})
|
||||||
|
except Exception:
|
||||||
|
get_logger(0).exception("Can't parse meta")
|
||||||
|
return None
|
||||||
80
kvmd/apps/kvmd/info/system.py
Normal file
80
kvmd/apps/kvmd/info/system.py
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
# ========================================================================== #
|
||||||
|
# #
|
||||||
|
# KVMD - The main Pi-KVM daemon. #
|
||||||
|
# #
|
||||||
|
# Copyright (C) 2018 Maxim Devaev <mdevaev@gmail.com> #
|
||||||
|
# #
|
||||||
|
# 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 asyncio
|
||||||
|
import platform
|
||||||
|
|
||||||
|
from typing import List
|
||||||
|
from typing import Dict
|
||||||
|
|
||||||
|
from ....logging import get_logger
|
||||||
|
|
||||||
|
from .... import aioproc
|
||||||
|
|
||||||
|
from .... import __version__
|
||||||
|
|
||||||
|
from .base import BaseInfoSubmanager
|
||||||
|
|
||||||
|
|
||||||
|
# =====
|
||||||
|
class SystemInfoSubmanager(BaseInfoSubmanager):
|
||||||
|
def __init__(self, streamer_cmd: List[str]) -> None:
|
||||||
|
self.__streamer_cmd = streamer_cmd
|
||||||
|
|
||||||
|
async def get_state(self) -> Dict:
|
||||||
|
streamer_info = await self.__get_streamer_info()
|
||||||
|
uname_info = platform.uname() # Uname using the internal cache
|
||||||
|
return {
|
||||||
|
"kvmd": {"version": __version__},
|
||||||
|
"streamer": streamer_info,
|
||||||
|
"kernel": {
|
||||||
|
field: getattr(uname_info, field)
|
||||||
|
for field in ["system", "release", "version", "machine"]
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
# =====
|
||||||
|
|
||||||
|
async def __get_streamer_info(self) -> Dict:
|
||||||
|
version = ""
|
||||||
|
features: Dict[str, bool] = {}
|
||||||
|
try:
|
||||||
|
path = self.__streamer_cmd[0]
|
||||||
|
((_, version), (_, features_text)) = await asyncio.gather(
|
||||||
|
aioproc.read_process([path, "--version"], err_to_null=True),
|
||||||
|
aioproc.read_process([path, "--features"], err_to_null=True),
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
get_logger(0).exception("Can't get streamer info")
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
for line in features_text.split("\n"):
|
||||||
|
(status, name) = map(str.strip, line.split(" "))
|
||||||
|
features[name] = (status == "+")
|
||||||
|
except Exception:
|
||||||
|
get_logger(0).exception("Can't parse streamer features")
|
||||||
|
return {
|
||||||
|
"app": os.path.basename(path),
|
||||||
|
"version": version,
|
||||||
|
"features": features,
|
||||||
|
}
|
||||||
@ -62,7 +62,6 @@ from ... import aioproc
|
|||||||
|
|
||||||
from .auth import AuthManager
|
from .auth import AuthManager
|
||||||
from .info import InfoManager
|
from .info import InfoManager
|
||||||
from .hw import HwManager
|
|
||||||
from .logreader import LogReader
|
from .logreader import LogReader
|
||||||
from .wol import WakeOnLan
|
from .wol import WakeOnLan
|
||||||
from .streamer import Streamer
|
from .streamer import Streamer
|
||||||
@ -82,7 +81,6 @@ from .api.auth import AuthApi
|
|||||||
from .api.auth import check_request_auth
|
from .api.auth import check_request_auth
|
||||||
|
|
||||||
from .api.info import InfoApi
|
from .api.info import InfoApi
|
||||||
from .api.hw import HwApi
|
|
||||||
from .api.log import LogApi
|
from .api.log import LogApi
|
||||||
from .api.wol import WolApi
|
from .api.wol import WolApi
|
||||||
from .api.hid import HidApi
|
from .api.hid import HidApi
|
||||||
@ -125,7 +123,6 @@ class KvmdServer(HttpServer): # pylint: disable=too-many-arguments,too-many-ins
|
|||||||
self,
|
self,
|
||||||
auth_manager: AuthManager,
|
auth_manager: AuthManager,
|
||||||
info_manager: InfoManager,
|
info_manager: InfoManager,
|
||||||
hw_manager: HwManager,
|
|
||||||
log_reader: LogReader,
|
log_reader: LogReader,
|
||||||
wol: WakeOnLan,
|
wol: WakeOnLan,
|
||||||
|
|
||||||
@ -149,21 +146,26 @@ class KvmdServer(HttpServer): # pylint: disable=too-many-arguments,too-many-ins
|
|||||||
self.__heartbeat = heartbeat
|
self.__heartbeat = heartbeat
|
||||||
|
|
||||||
self.__components = [
|
self.__components = [
|
||||||
|
*[
|
||||||
_Component("Auth manager", "", auth_manager),
|
_Component("Auth manager", "", auth_manager),
|
||||||
_Component("Info manager", "info_state", info_manager),
|
],
|
||||||
_Component("HW manager", "hw_state", hw_manager),
|
*[
|
||||||
|
_Component(f"Info manager ({sub})", f"info_{sub}_state", info_manager.get_submanager(sub))
|
||||||
|
for sub in info_manager.get_subs()
|
||||||
|
],
|
||||||
|
*[
|
||||||
_Component("Wake-on-LAN", "wol_state", wol),
|
_Component("Wake-on-LAN", "wol_state", wol),
|
||||||
_Component("HID", "hid_state", hid),
|
_Component("HID", "hid_state", hid),
|
||||||
_Component("ATX", "atx_state", atx),
|
_Component("ATX", "atx_state", atx),
|
||||||
_Component("MSD", "msd_state", msd),
|
_Component("MSD", "msd_state", msd),
|
||||||
_Component("Streamer", "streamer_state", streamer),
|
_Component("Streamer", "streamer_state", streamer),
|
||||||
|
],
|
||||||
]
|
]
|
||||||
|
|
||||||
self.__apis: List[object] = [
|
self.__apis: List[object] = [
|
||||||
self,
|
self,
|
||||||
AuthApi(auth_manager),
|
AuthApi(auth_manager),
|
||||||
InfoApi(info_manager),
|
InfoApi(info_manager),
|
||||||
HwApi(hw_manager),
|
|
||||||
LogApi(log_reader),
|
LogApi(log_reader),
|
||||||
WolApi(wol),
|
WolApi(wol),
|
||||||
HidApi(hid, keymap_path),
|
HidApi(hid, keymap_path),
|
||||||
@ -325,7 +327,7 @@ class KvmdServer(HttpServer): # pylint: disable=too-many-arguments,too-many-ins
|
|||||||
except Exception:
|
except Exception:
|
||||||
logger.exception("Cleanup error on %s", component.name)
|
logger.exception("Cleanup error on %s", component.name)
|
||||||
|
|
||||||
async def __broadcast_event(self, event_type: str, event: Dict) -> None:
|
async def __broadcast_event(self, event_type: str, event: Optional[Dict]) -> None:
|
||||||
if self.__ws_clients:
|
if self.__ws_clients:
|
||||||
await asyncio.gather(*[
|
await asyncio.gather(*[
|
||||||
client.ws.send_str(json.dumps({
|
client.ws.send_str(json.dumps({
|
||||||
|
|||||||
@ -149,9 +149,9 @@ class _Client(RfbClient): # pylint: disable=too-many-instance-attributes
|
|||||||
self.__kvmd_ws = None
|
self.__kvmd_ws = None
|
||||||
|
|
||||||
async def __process_ws_event(self, event: Dict) -> None:
|
async def __process_ws_event(self, event: Dict) -> None:
|
||||||
if event["event_type"] == "info_state":
|
if event["event_type"] == "info_meta_state":
|
||||||
try:
|
try:
|
||||||
host = event["event"]["meta"]["server"]["host"]
|
host = event["event"]["server"]["host"]
|
||||||
except Exception:
|
except Exception:
|
||||||
host = None
|
host = None
|
||||||
else:
|
else:
|
||||||
|
|||||||
1
setup.py
1
setup.py
@ -90,6 +90,7 @@ def main() -> None:
|
|||||||
"kvmd.clients",
|
"kvmd.clients",
|
||||||
"kvmd.apps",
|
"kvmd.apps",
|
||||||
"kvmd.apps.kvmd",
|
"kvmd.apps.kvmd",
|
||||||
|
"kvmd.apps.kvmd.info",
|
||||||
"kvmd.apps.kvmd.api",
|
"kvmd.apps.kvmd.api",
|
||||||
"kvmd.apps.otg",
|
"kvmd.apps.otg",
|
||||||
"kvmd.apps.otg.hid",
|
"kvmd.apps.otg.hid",
|
||||||
|
|||||||
@ -2,6 +2,7 @@ kvmd:
|
|||||||
server:
|
server:
|
||||||
unix_mode: 0666
|
unix_mode: 0666
|
||||||
|
|
||||||
|
info:
|
||||||
hw:
|
hw:
|
||||||
procfs_prefix: /fake_procfs
|
procfs_prefix: /fake_procfs
|
||||||
sysfs_prefix: /fake_sysfs
|
sysfs_prefix: /fake_sysfs
|
||||||
|
|||||||
@ -2,6 +2,7 @@ kvmd:
|
|||||||
server:
|
server:
|
||||||
unix_mode: 0666
|
unix_mode: 0666
|
||||||
|
|
||||||
|
info:
|
||||||
hw:
|
hw:
|
||||||
procfs_prefix: /fake_procfs
|
procfs_prefix: /fake_procfs
|
||||||
sysfs_prefix: /fake_sysfs
|
sysfs_prefix: /fake_sysfs
|
||||||
|
|||||||
@ -51,7 +51,7 @@ function __setAppText() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function __loadKvmdInfo() {
|
function __loadKvmdInfo() {
|
||||||
let http = tools.makeRequest("GET", "/api/info", function() {
|
let http = tools.makeRequest("GET", "/api/info?fields=meta,extras", function() {
|
||||||
if (http.readyState === 4) {
|
if (http.readyState === 4) {
|
||||||
if (http.status === 200) {
|
if (http.status === 200) {
|
||||||
let info = JSON.parse(http.responseText).result;
|
let info = JSON.parse(http.responseText).result;
|
||||||
|
|||||||
@ -55,36 +55,37 @@ export function Session() {
|
|||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
var __setAboutInfo = function(state) {
|
var __setAboutInfoSystem = function(state) {
|
||||||
if (state.meta != null) {
|
$("about-version").innerHTML = `
|
||||||
let text = JSON.stringify(state.meta, undefined, 4).replace(/ /g, " ").replace(/\n/g, "<br>");
|
KVMD: <span class="code-comment">${state.kvmd.version}</span><br>
|
||||||
|
<hr>
|
||||||
|
Streamer: <span class="code-comment">${state.streamer.version} (${state.streamer.app})</span>
|
||||||
|
${__formatStreamerFeatures(state.streamer.features)}
|
||||||
|
<hr>
|
||||||
|
${state.kernel.system} kernel:
|
||||||
|
${__formatUname(state.kernel)}
|
||||||
|
`;
|
||||||
|
};
|
||||||
|
|
||||||
|
var __setAboutInfoMeta = function(state) {
|
||||||
|
if (state != null) {
|
||||||
|
let text = JSON.stringify(state, undefined, 4).replace(/ /g, " ").replace(/\n/g, "<br>");
|
||||||
$("about-meta").innerHTML = `
|
$("about-meta").innerHTML = `
|
||||||
<span class="code-comment">// The Pi-KVM metadata.<br>
|
<span class="code-comment">// The Pi-KVM metadata.<br>
|
||||||
// You can get this json using handle <a target="_blank" href="/api/info">/api/info</a>.<br>
|
// You can get this JSON using handle <a target="_blank" href="/api/info?fields=meta">/api/info?fields=meta</a>.<br>
|
||||||
// In the standard configuration this data<br>
|
// In the standard configuration this data<br>
|
||||||
// is specified in the file /etc/kvmd/meta.yaml.</span><br>
|
// is specified in the file /etc/kvmd/meta.yaml.</span><br>
|
||||||
<br>
|
<br>
|
||||||
${text}
|
${text}
|
||||||
`;
|
`;
|
||||||
if (state.meta.server && state.meta.server.host) {
|
if (state.server && state.server.host) {
|
||||||
$("kvmd-meta-server-host").innerHTML = `Server: ${state.meta.server.host}`;
|
$("kvmd-meta-server-host").innerHTML = `Server: ${state.server.host}`;
|
||||||
document.title = `Pi-KVM Session: ${state.meta.server.host}`;
|
document.title = `Pi-KVM Session: ${state.server.host}`;
|
||||||
} else {
|
} else {
|
||||||
$("kvmd-meta-server-host").innerHTML = "";
|
$("kvmd-meta-server-host").innerHTML = "";
|
||||||
document.title = "Pi-KVM Session";
|
document.title = "Pi-KVM Session";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let sys = state.system;
|
|
||||||
$("about-version").innerHTML = `
|
|
||||||
KVMD: <span class="code-comment">${sys.kvmd.version}</span><br>
|
|
||||||
<hr>
|
|
||||||
Streamer: <span class="code-comment">${sys.streamer.version} (${sys.streamer.app})</span>
|
|
||||||
${__formatStreamerFeatures(sys.streamer.features)}
|
|
||||||
<hr>
|
|
||||||
${sys.kernel.system} kernel:
|
|
||||||
${__formatUname(sys.kernel)}
|
|
||||||
`;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var __formatStreamerFeatures = function(features) {
|
var __formatStreamerFeatures = function(features) {
|
||||||
@ -157,7 +158,8 @@ export function Session() {
|
|||||||
let data = JSON.parse(event.data);
|
let data = JSON.parse(event.data);
|
||||||
switch (data.event_type) {
|
switch (data.event_type) {
|
||||||
case "pong": __missed_heartbeats = 0; break;
|
case "pong": __missed_heartbeats = 0; break;
|
||||||
case "info_state": __setAboutInfo(data.event); break;
|
case "info_system_state": __setAboutInfoSystem(data.event); break;
|
||||||
|
case "info_meta_state": __setAboutInfoMeta(data.event); break;
|
||||||
case "wol_state": __wol.setState(data.event); break;
|
case "wol_state": __wol.setState(data.event); break;
|
||||||
case "hid_state": __hid.setState(data.event); break;
|
case "hid_state": __hid.setState(data.event); break;
|
||||||
case "atx_state": __atx.setState(data.event); break;
|
case "atx_state": __atx.setState(data.event); break;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user