summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--configs/kvmd/kvmd.v1-hdmi.yaml10
-rw-r--r--configs/kvmd/kvmd.v1-vga.yaml10
-rw-r--r--configs/kvmd/meta.yaml9
-rw-r--r--kvmd/application.py32
-rw-r--r--kvmd/apps/kvmd/__init__.py5
-rw-r--r--kvmd/apps/kvmd/atx.py13
-rw-r--r--kvmd/apps/kvmd/server.py21
-rw-r--r--kvmd/apps/kvmd/streamer.py12
-rw-r--r--kvmd/logging.py2
-rw-r--r--kvmd/yaml.py31
-rw-r--r--testenv/kvmd.yaml7
12 files changed, 97 insertions, 57 deletions
diff --git a/Makefile b/Makefile
index 68a8d6ec..04d6ac06 100644
--- a/Makefile
+++ b/Makefile
@@ -7,7 +7,7 @@ TESTENV_CMD ?= /bin/bash -c " \
&& rm -rf /etc/nginx/* \
&& cp -r /usr/share/kvmd/configs/nginx/* /etc/nginx \
&& mkdir -p /etc/kvmd \
- && cp /usr/share/kvmd/configs/kvmd/logging.yaml /etc/kvmd/logging.yaml \
+ && cp /usr/share/kvmd/configs/kvmd/{meta.yaml,logging.yaml} /etc/kvmd \
&& cp /testenv/kvmd.yaml /etc/kvmd \
&& nginx -c /etc/nginx/nginx.conf \
&& ln -s $(TESTENV_VIDEO) /dev/kvmd-streamer \
diff --git a/configs/kvmd/kvmd.v1-hdmi.yaml b/configs/kvmd/kvmd.v1-hdmi.yaml
index 1ac41a12..43b3278e 100644
--- a/configs/kvmd/kvmd.v1-hdmi.yaml
+++ b/configs/kvmd/kvmd.v1-hdmi.yaml
@@ -1,9 +1,15 @@
+# Don't touch this file otherwise your device may stop working.
+# You can find a workable configuration in /usr/share/kvmd/configs/kvmd.
+
kvmd:
server:
host: 127.0.0.1
port: 8081
heartbeat: 3.0
+ info:
+ meta: /etc/kvmd/meta.yaml
+
log:
services:
- kvmd.service
@@ -26,7 +32,6 @@ kvmd:
click_delay: 0.1
long_click_delay: 5.5
-
state_poll: 0.1
msd:
@@ -49,6 +54,7 @@ kvmd:
init_delay: 1.0
init_restart_after: 0.0
shutdown_delay: 10.0
+ state_poll: 1.0
quality: 80
desired_fps: 0
@@ -71,6 +77,4 @@ kvmd:
- "--port={port}"
- "--drop-same-frames=30"
- state_poll: 1.0
-
logging: !include logging.yaml
diff --git a/configs/kvmd/kvmd.v1-vga.yaml b/configs/kvmd/kvmd.v1-vga.yaml
index 3065c262..5993176f 100644
--- a/configs/kvmd/kvmd.v1-vga.yaml
+++ b/configs/kvmd/kvmd.v1-vga.yaml
@@ -1,9 +1,15 @@
+# Don't touch this file otherwise your device may stop working.
+# You can find a workable configuration in /usr/share/kvmd/configs/kvmd.
+
kvmd:
server:
host: 127.0.0.1
port: 8081
heartbeat: 3.0
+ info:
+ meta: /etc/kvmd/meta.yaml
+
log:
services:
- kvmd.service
@@ -26,7 +32,6 @@ kvmd:
click_delay: 0.1
long_click_delay: 5.5
-
state_poll: 0.1
msd:
@@ -49,6 +54,7 @@ kvmd:
init_delay: 1.0
init_restart_after: 1.0
shutdown_delay: 10.0
+ state_poll: 1.0
quality: 80
desired_fps: 0
@@ -72,6 +78,4 @@ kvmd:
- "--host={host}"
- "--port={port}"
- state_poll: 1.0
-
logging: !include logging.yaml
diff --git a/configs/kvmd/meta.yaml b/configs/kvmd/meta.yaml
new file mode 100644
index 00000000..65524997
--- /dev/null
+++ b/configs/kvmd/meta.yaml
@@ -0,0 +1,9 @@
+# You can write down any information and it will be available
+# at the address /kvmd/info (if you use default nginx config).
+# If server.host (str) will be defained then this value
+# will be displayed in the web interface.
+
+server:
+ host: localhost
+
+kvm: {}
diff --git a/kvmd/application.py b/kvmd/application.py
index 31a57925..3db8d20d 100644
--- a/kvmd/application.py
+++ b/kvmd/application.py
@@ -1,15 +1,10 @@
-import os
import argparse
import logging
import logging.config
from typing import Dict
-from typing import IO
-from typing import Any
-import yaml
-import yaml.loader
-import yaml.nodes
+from .yaml import load_yaml_file
# =====
@@ -18,32 +13,9 @@ def init() -> Dict:
parser.add_argument("-c", "--config", required=True, metavar="<path>")
options = parser.parse_args()
- config: Dict = _load_yaml_file(options.config)
+ config: Dict = load_yaml_file(options.config)
logging.captureWarnings(True)
logging.config.dictConfig(config["logging"])
return config
-
-
-# =====
-def _load_yaml_file(path: str) -> Any:
- with open(path) as yaml_file:
- try:
- return yaml.load(yaml_file, _YamlLoader)
- except Exception:
- # Reraise internal exception as standard ValueError and show the incorrect file
- raise ValueError("Incorrect YAML syntax in file '{}'".format(path))
-
-
-class _YamlLoader(yaml.loader.Loader): # pylint: disable=too-many-ancestors
- def __init__(self, yaml_file: IO) -> None:
- yaml.loader.Loader.__init__(self, yaml_file)
- self.__root = os.path.dirname(yaml_file.name)
-
- def include(self, node: yaml.nodes.Node) -> str:
- path = os.path.join(self.__root, self.construct_scalar(node)) # pylint: disable=no-member
- return _load_yaml_file(path)
-
-
-_YamlLoader.add_constructor("!include", _YamlLoader.include) # pylint: disable=no-member
diff --git a/kvmd/apps/kvmd/__init__.py b/kvmd/apps/kvmd/__init__.py
index 099fd192..103d8be8 100644
--- a/kvmd/apps/kvmd/__init__.py
+++ b/kvmd/apps/kvmd/__init__.py
@@ -42,6 +42,7 @@ def main() -> None:
reset_switch=int(config["atx"]["pinout"]["reset_switch"]),
click_delay=float(config["atx"]["click_delay"]),
long_click_delay=float(config["atx"]["long_click_delay"]),
+ state_poll=float(config["atx"]["state_poll"]),
)
msd = MassStorageDevice(
@@ -62,6 +63,7 @@ def main() -> None:
sync_delay=float(config["streamer"]["sync_delay"]),
init_delay=float(config["streamer"]["init_delay"]),
init_restart_after=float(config["streamer"]["init_restart_after"]),
+ state_poll=float(config["streamer"]["state_poll"]),
quality=int(config["streamer"]["quality"]),
desired_fps=int(config["streamer"]["desired_fps"]),
@@ -83,9 +85,8 @@ def main() -> None:
msd=msd,
streamer=streamer,
+ meta_path=str(config["info"]["meta"]),
heartbeat=float(config["server"]["heartbeat"]),
- atx_state_poll=float(config["atx"]["state_poll"]),
- streamer_state_poll=float(config["streamer"]["state_poll"]),
streamer_shutdown_delay=float(config["streamer"]["shutdown_delay"]),
msd_chunk_size=int(config["msd"]["chunk_size"]),
diff --git a/kvmd/apps/kvmd/atx.py b/kvmd/apps/kvmd/atx.py
index d49708e0..8444c097 100644
--- a/kvmd/apps/kvmd/atx.py
+++ b/kvmd/apps/kvmd/atx.py
@@ -1,6 +1,7 @@
import asyncio
from typing import Dict
+from typing import AsyncGenerator
from ...logging import get_logger
@@ -13,16 +14,17 @@ class AtxIsBusy(aioregion.RegionIsBusyError):
pass
-class Atx:
+class Atx: # pylint: disable=too-many-instance-attributes
def __init__(
self,
power_led: int,
hdd_led: int,
-
power_switch: int,
reset_switch: int,
+
click_delay: float,
long_click_delay: float,
+ state_poll: float,
) -> None:
self.__power_led = gpio.set_input(power_led)
@@ -33,6 +35,8 @@ class Atx:
self.__click_delay = click_delay
self.__long_click_delay = long_click_delay
+ self.__state_poll = state_poll
+
self.__region = aioregion.AioExclusiveRegion(AtxIsBusy)
def get_state(self) -> Dict:
@@ -44,6 +48,11 @@ class Atx:
},
}
+ async def poll_state(self) -> AsyncGenerator[Dict, None]:
+ while True:
+ yield self.get_state()
+ await asyncio.sleep(self.__state_poll)
+
async def click_power(self) -> None:
await self.__click(self.__power_switch, self.__click_delay)
get_logger().info("Clicked power")
diff --git a/kvmd/apps/kvmd/server.py b/kvmd/apps/kvmd/server.py
index 04ce140f..ae66cbc4 100644
--- a/kvmd/apps/kvmd/server.py
+++ b/kvmd/apps/kvmd/server.py
@@ -18,6 +18,8 @@ from ...logging import Log
from ...aioregion import RegionIsBusyError
+from ...yaml import load_yaml_file
+
from ... import __version__
from .hid import Hid
@@ -111,9 +113,8 @@ class Server: # pylint: disable=too-many-instance-attributes
msd: MassStorageDevice,
streamer: Streamer,
+ meta_path: str,
heartbeat: float,
- atx_state_poll: float,
- streamer_state_poll: float,
streamer_shutdown_delay: float,
msd_chunk_size: int,
@@ -126,9 +127,8 @@ class Server: # pylint: disable=too-many-instance-attributes
self.__msd = msd
self.__streamer = streamer
+ self.__meta_path = meta_path
self.__heartbeat = heartbeat
- self.__atx_state_poll = atx_state_poll
- self.__streamer_state_poll = streamer_state_poll
self.__streamer_shutdown_delay = streamer_shutdown_delay
self.__msd_chunk_size = msd_chunk_size
@@ -190,6 +190,7 @@ class Server: # pylint: disable=too-many-instance-attributes
"streamer": await self.__streamer.get_version(),
},
"streamer": self.__streamer.get_app(),
+ "meta": load_yaml_file(self.__meta_path),
})
@_wrap_exceptions_for_web("Log error")
@@ -198,7 +199,7 @@ class Server: # pylint: disable=too-many-instance-attributes
follow = _valid_bool("follow", request.query.get("follow", "false"))
response = aiohttp.web.StreamResponse(status=200, reason="OK", headers={"Content-Type": "text/plain"})
await response.prepare(request)
- async for record in self.__log.log(seek, follow):
+ async for record in self.__log.poll_log(seek, follow):
await response.write(("[%s %s] --- %s" % (
record["dt"].strftime("%Y-%m-%d %H:%M:%S"),
record["service"],
@@ -431,17 +432,15 @@ class Server: # pylint: disable=too-many-instance-attributes
@_system_task
async def __poll_atx_state(self) -> None:
- while True:
+ async for state in self.__atx.poll_state():
if self.__sockets:
- await self.__broadcast_event("atx_state", **self.__atx.get_state())
- await asyncio.sleep(self.__atx_state_poll)
+ await self.__broadcast_event("atx_state", **state)
@_system_task
async def __poll_streamer_state(self) -> None:
- while True:
+ async for state in self.__streamer.poll_state():
if self.__sockets:
- await self.__broadcast_event("streamer_state", **(await self.__streamer.get_state()))
- await asyncio.sleep(self.__streamer_state_poll)
+ await self.__broadcast_event("streamer_state", **state)
async def __broadcast_event(self, event: str, **kwargs: Dict) -> None:
await asyncio.gather(*[
diff --git a/kvmd/apps/kvmd/streamer.py b/kvmd/apps/kvmd/streamer.py
index da82ade1..25fe7527 100644
--- a/kvmd/apps/kvmd/streamer.py
+++ b/kvmd/apps/kvmd/streamer.py
@@ -4,6 +4,7 @@ import asyncio.subprocess
from typing import List
from typing import Dict
+from typing import AsyncGenerator
from typing import Optional
import aiohttp
@@ -15,13 +16,15 @@ from ... import gpio
# =====
class Streamer: # pylint: disable=too-many-instance-attributes
- def __init__( # pylint: disable=too-many-arguments
+ def __init__( # pylint: disable=too-many-arguments,too-many-locals
self,
cap_power: int,
conv_power: int,
+
sync_delay: float,
init_delay: float,
init_restart_after: float,
+ state_poll: float,
quality: int,
desired_fps: int,
@@ -38,9 +41,11 @@ class Streamer: # pylint: disable=too-many-instance-attributes
self.__cap_power = (gpio.set_output(cap_power) if cap_power > 0 else cap_power)
self.__conv_power = (gpio.set_output(conv_power) if conv_power > 0 else conv_power)
+
self.__sync_delay = sync_delay
self.__init_delay = init_delay
self.__init_restart_after = init_restart_after
+ self.__state_poll = state_poll
self.__params = {
"quality": quality,
@@ -99,6 +104,11 @@ class Streamer: # pylint: disable=too-many-instance-attributes
"state": state,
}
+ async def poll_state(self) -> AsyncGenerator[Dict, None]:
+ while True:
+ yield (await self.get_state())
+ await asyncio.sleep(self.__state_poll)
+
def get_app(self) -> str:
return os.path.basename(self.__cmd[0])
diff --git a/kvmd/logging.py b/kvmd/logging.py
index 0efb9cb4..11a8dcf1 100644
--- a/kvmd/logging.py
+++ b/kvmd/logging.py
@@ -33,7 +33,7 @@ class Log:
self.__services = services
self.__loop = loop
- async def log(self, seek: int, follow: bool) -> AsyncGenerator[Dict, None]:
+ async def poll_log(self, seek: int, follow: bool) -> AsyncGenerator[Dict, None]:
reader = systemd.journal.Reader()
reader.this_boot()
reader.this_machine()
diff --git a/kvmd/yaml.py b/kvmd/yaml.py
new file mode 100644
index 00000000..cd7ae4fd
--- /dev/null
+++ b/kvmd/yaml.py
@@ -0,0 +1,31 @@
+import os
+
+from typing import IO
+from typing import Any
+
+import yaml
+import yaml.loader
+import yaml.nodes
+
+
+# =====
+def load_yaml_file(path: str) -> Any:
+ with open(path) as yaml_file:
+ try:
+ return yaml.load(yaml_file, _YamlLoader)
+ except Exception:
+ # Reraise internal exception as standard ValueError and show the incorrect file
+ raise ValueError("Incorrect YAML syntax in file '{}'".format(path))
+
+
+class _YamlLoader(yaml.loader.Loader): # pylint: disable=too-many-ancestors
+ def __init__(self, yaml_file: IO) -> None:
+ yaml.loader.Loader.__init__(self, yaml_file)
+ self.__root = os.path.dirname(yaml_file.name)
+
+ def include(self, node: yaml.nodes.Node) -> str:
+ path = os.path.join(self.__root, self.construct_scalar(node)) # pylint: disable=no-member
+ return load_yaml_file(path)
+
+
+_YamlLoader.add_constructor("!include", _YamlLoader.include) # pylint: disable=no-member
diff --git a/testenv/kvmd.yaml b/testenv/kvmd.yaml
index 34489afb..3ab0a25b 100644
--- a/testenv/kvmd.yaml
+++ b/testenv/kvmd.yaml
@@ -4,6 +4,9 @@ kvmd:
port: 8081
heartbeat: 3.0
+ info:
+ meta: /etc/kvmd/meta.yaml
+
log:
services:
- kvmd.service
@@ -25,7 +28,6 @@ kvmd:
click_delay: 0.1
long_click_delay: 5.5
-
state_poll: 0.1
msd:
@@ -48,6 +50,7 @@ kvmd:
init_delay: 1.0
init_restart_after: 1.0
shutdown_delay: 10.0
+ state_poll: 1.0
quality: 80
desired_fps: 0
@@ -66,6 +69,4 @@ kvmd:
- "--host=0.0.0.0"
- "--port={port}"
- state_poll: 1.0
-
logging: !include logging.yaml