summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDevaev Maxim <[email protected]>2018-07-07 23:37:38 +0000
committerDevaev Maxim <[email protected]>2018-07-07 23:37:38 +0000
commit476018aeb82398afbf53d7a91e3b8e30ff0b2851 (patch)
treeb790400ed29205010d702266c7da40b16293e997
parentf9a69c7467229dc1bf864d374f252b0cc9017bcd (diff)
udev instead own bycicles
-rw-r--r--kvmd/kvmd/__init__.py7
-rw-r--r--kvmd/kvmd/extras/explorehw/__init__.py48
-rw-r--r--kvmd/kvmd/extras/explorehw/__main__.py2
-rw-r--r--kvmd/kvmd/msd.py51
-rw-r--r--kvmd/kvmd/streamer.py59
-rwxr-xr-xkvmd/setup.py2
-rw-r--r--os/platforms/v1/Dockerfile.part3
-rw-r--r--os/platforms/v1/kvmd.yaml5
-rw-r--r--os/platforms/v1/sysctl.conf (renamed from os/platforms/v1/99-pikvm.conf)0
-rw-r--r--os/platforms/v1/udev.rules4
10 files changed, 30 insertions, 151 deletions
diff --git a/kvmd/kvmd/__init__.py b/kvmd/kvmd/__init__.py
index c4b8dc9a..422a531c 100644
--- a/kvmd/kvmd/__init__.py
+++ b/kvmd/kvmd/__init__.py
@@ -34,16 +34,15 @@ def main() -> None:
)
msd = MassStorageDevice(
- bind=str(config["msd"]["bind"]),
+ device_path=str(config["msd"]["device"]),
init_delay=float(config["msd"]["init_delay"]),
write_meta=bool(config["msd"]["write_meta"]),
loop=loop,
)
streamer = Streamer(
- cap_power=int(config["streamer"]["pinout"].get("cap", -1)),
- conv_power=int(config["streamer"]["pinout"].get("conv", -1)),
- bind=str(config["streamer"].get("bind", "")),
+ cap_power=int(config["streamer"]["pinout"]["cap"]),
+ conv_power=int(config["streamer"]["pinout"]["conv"]),
sync_delay=float(config["streamer"]["sync_delay"]),
init_delay=float(config["streamer"]["init_delay"]),
width=int(config["streamer"]["size"]["width"]),
diff --git a/kvmd/kvmd/extras/explorehw/__init__.py b/kvmd/kvmd/extras/explorehw/__init__.py
deleted file mode 100644
index 42ade82f..00000000
--- a/kvmd/kvmd/extras/explorehw/__init__.py
+++ /dev/null
@@ -1,48 +0,0 @@
-import argparse
-
-from ... import msd
-from ... import streamer
-
-
-# =====
-def _probe_msd(path: str) -> bool:
- info = msd.explore_device(path)
- if info:
- print("It's a mass-storage device")
- print("--------------------------")
- print("Path: ", info.path)
- print("Bind: ", info.bind)
- print("Size: ", info.size)
- print("Manufacturer:", info.manufacturer)
- print("Product: ", info.product)
- print("Serial: ", info.serial)
- print("Image name: ", info.image_name)
- assert msd.locate_by_bind(info.bind), info.bind
- return bool(info)
-
-
-def _probe_streamer(path: str) -> bool:
- info = streamer.explore_device(path)
- if info:
- print("It's a streamer device")
- print("----------------------")
- print("Path: ", info.path)
- print("Bind: ", info.bind)
- print("Driver:", info.driver)
- assert streamer.locate_by_bind(info.bind), info.bind
- return bool(info)
-
-
-def main() -> None:
- parser = argparse.ArgumentParser()
- parser.add_argument("device")
- options = parser.parse_args()
-
- for probe in [
- _probe_msd,
- _probe_streamer,
- ]:
- if probe(options.device):
- break
- else:
- raise RuntimeError("Can't recognize device")
diff --git a/kvmd/kvmd/extras/explorehw/__main__.py b/kvmd/kvmd/extras/explorehw/__main__.py
deleted file mode 100644
index 031df43e..00000000
--- a/kvmd/kvmd/extras/explorehw/__main__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-from . import main
-main()
diff --git a/kvmd/kvmd/msd.py b/kvmd/kvmd/msd.py
index c6694cb4..4a6b2554 100644
--- a/kvmd/kvmd/msd.py
+++ b/kvmd/kvmd/msd.py
@@ -25,7 +25,7 @@ class MassStorageError(Exception):
class IsNotOperationalError(MassStorageError):
def __init__(self) -> None:
- super().__init__("Missing bind for mass-storage device")
+ super().__init__("Missing path for mass-storage device")
class AlreadyConnectedToPcError(MassStorageError):
@@ -50,7 +50,6 @@ class IsBusyError(MassStorageError):
class MassStorageDeviceInfo(NamedTuple):
path: str
- bind: str
size: int
manufacturer: str
product: str
@@ -108,10 +107,6 @@ def explore_device(path: str) -> Optional[MassStorageDeviceInfo]:
except KeyError:
return None
- interface_device = block_device.find_parent("usb", "usb_interface")
- if not interface_device:
- return None
-
usb_device = block_device.find_parent("usb", "usb_device")
if not usb_device:
return None
@@ -122,7 +117,6 @@ def explore_device(path: str) -> Optional[MassStorageDeviceInfo]:
return MassStorageDeviceInfo(
path=path,
- bind=interface_device.sys_name,
size=size,
manufacturer=usb_device.attributes.asstring("manufacturer").strip(),
product=usb_device.attributes.asstring("product").strip(),
@@ -131,24 +125,11 @@ def explore_device(path: str) -> Optional[MassStorageDeviceInfo]:
)
-def locate_by_bind(bind: str) -> str:
- ctx = pyudev.Context()
- for device in ctx.list_devices(subsystem="block"):
- storage_device = device.find_parent("usb", "usb_interface")
- if storage_device:
- try:
- device.attributes.asint("partititon")
- except KeyError:
- if storage_device.sys_name == bind:
- return os.path.join("/dev", device.sys_name)
- return ""
-
-
def _operated_and_locked(method: Callable) -> Callable:
async def wrap(self: "MassStorageDevice", *args: Any, **kwargs: Any) -> Any:
if self._device_file: # pylint: disable=protected-access
raise IsBusyError()
- if not self._bind: # pylint: disable=protected-access
+ if not self._device_path: # pylint: disable=protected-access
IsNotOperationalError()
async with self._lock: # pylint: disable=protected-access
return (await method(self, *args, **kwargs))
@@ -156,8 +137,15 @@ def _operated_and_locked(method: Callable) -> Callable:
class MassStorageDevice: # pylint: disable=too-many-instance-attributes
- def __init__(self, bind: str, init_delay: float, write_meta: bool, loop: asyncio.AbstractEventLoop) -> None:
- self._bind = bind
+ def __init__(
+ self,
+ device_path: str,
+ init_delay: float,
+ write_meta: bool,
+ loop: asyncio.AbstractEventLoop,
+ ) -> None:
+
+ self._device_path = device_path
self.__init_delay = init_delay
self.__write_meta = write_meta
self.__loop = loop
@@ -168,8 +156,8 @@ class MassStorageDevice: # pylint: disable=too-many-instance-attributes
self.__writed = 0
logger = get_logger(0)
- if self._bind:
- logger.info("Using bind %r as mass-storage device", self._bind)
+ if self._device_path:
+ logger.info("Using %r as mass-storage device", self._device_path)
try:
logger.info("Enabled metadata writing")
loop.run_until_complete(self.connect_to_kvm(no_delay=True))
@@ -179,9 +167,9 @@ class MassStorageDevice: # pylint: disable=too-many-instance-attributes
else:
log = logger.exception
log("Mass-storage device is not operational: %s", err)
- self._bind = ""
+ self._device_path = ""
else:
- logger.warning("Missing bind; mass-storage device is not operational")
+ logger.warning("Mass-storage device is not operational")
@_operated_and_locked
async def connect_to_kvm(self, no_delay: bool=False) -> None:
@@ -203,7 +191,7 @@ class MassStorageDevice: # pylint: disable=too-many-instance-attributes
def get_state(self) -> Dict:
return {
- "in_operate": bool(self._bind),
+ "in_operate": bool(self._device_path),
"connected_to": ("kvm" if self.__device_info else "server"),
"is_busy": bool(self._device_file),
"writed": self.__writed,
@@ -255,12 +243,9 @@ class MassStorageDevice: # pylint: disable=too-many-instance-attributes
await self.__close_device_file()
async def __reread_device_info(self) -> None:
- device_path = await self.__loop.run_in_executor(None, locate_by_bind, self._bind)
- if not device_path:
- raise MassStorageError("Can't locate device by bind %r" % (self._bind))
- device_info = await self.__loop.run_in_executor(None, explore_device, device_path)
+ device_info = await self.__loop.run_in_executor(None, explore_device, self._device_path)
if not device_info:
- raise MassStorageError("Can't explore device %r" % (device_path))
+ raise MassStorageError("Can't explore device %r" % (self._device_path))
self.__device_info = device_info
async def __close_device_file(self) -> None:
diff --git a/kvmd/kvmd/streamer.py b/kvmd/kvmd/streamer.py
index c5e9fd41..14bf8159 100644
--- a/kvmd/kvmd/streamer.py
+++ b/kvmd/kvmd/streamer.py
@@ -1,14 +1,9 @@
-import os
import asyncio
import asyncio.subprocess
from typing import List
from typing import Dict
-from typing import NamedTuple
from typing import Optional
-from typing import Any
-
-import pyudev
from .logging import get_logger
@@ -16,52 +11,11 @@ from . import gpio
# =====
-class StreamerDeviceInfo(NamedTuple):
- path: str
- bind: str
- driver: str
-
-
-def explore_device(path: str) -> Optional[StreamerDeviceInfo]:
- # udevadm info -a -p $(udevadm info -q path -n /dev/sda)
- ctx = pyudev.Context()
-
- video_device = pyudev.Devices.from_device_file(ctx, path)
- if video_device.subsystem != "video4linux":
- return None
- try:
- if int(video_device.attributes.get("index")) != 0:
- # My strange laptop configuration
- return None
- except ValueError:
- return None
-
- interface_device = video_device.find_parent("usb", "usb_interface")
- if not interface_device:
- return None
-
- return StreamerDeviceInfo(
- path=path,
- bind=interface_device.sys_name,
- driver=interface_device.driver,
- )
-
-
-def locate_by_bind(bind: str) -> str:
- ctx = pyudev.Context()
- for device in ctx.list_devices(subsystem="video4linux"):
- interface_device = device.find_parent("usb", "usb_interface")
- if interface_device and interface_device.sys_name == bind:
- return os.path.join("/dev", device.sys_name)
- return ""
-
-
class Streamer: # pylint: disable=too-many-instance-attributes
def __init__(
self,
cap_power: int,
conv_power: int,
- bind: str,
sync_delay: float,
init_delay: float,
width: int,
@@ -70,11 +24,8 @@ class Streamer: # pylint: disable=too-many-instance-attributes
loop: asyncio.AbstractEventLoop,
) -> None:
- assert cmd, cmd
-
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.__bind = bind
self.__sync_delay = sync_delay
self.__init_delay = init_delay
self.__width = width
@@ -132,15 +83,7 @@ class Streamer: # pylint: disable=too-many-instance-attributes
while True: # pylint: disable=too-many-nested-blocks
proc: Optional[asyncio.subprocess.Process] = None # pylint: disable=no-member
try:
- cmd_placeholders: Dict[str, Any] = {"width": self.__width, "height": self.__height}
- if self.__bind:
- logger.info("Using bind %r as streamer device", self.__bind)
- device_path = await self.__loop.run_in_executor(None, locate_by_bind, self.__bind)
- if not device_path:
- raise RuntimeError("Can't locate device by bind %r" % (self.__bind))
- cmd_placeholders["device"] = device_path
- cmd = [part.format(**cmd_placeholders) for part in self.__cmd]
-
+ cmd = [part.format(width=self.__width, height=self.__height) for part in self.__cmd]
proc = await asyncio.create_subprocess_exec(
*cmd,
stdout=asyncio.subprocess.PIPE,
diff --git a/kvmd/setup.py b/kvmd/setup.py
index 25633f4b..d0d69429 100755
--- a/kvmd/setup.py
+++ b/kvmd/setup.py
@@ -24,7 +24,6 @@ def main() -> None:
"kvmd.extras",
"kvmd.extras.cleanup",
"kvmd.extras.wscli",
- "kvmd.extras.explorehw",
],
entry_points={
@@ -32,7 +31,6 @@ def main() -> None:
"kvmd = kvmd:main",
"kvmd-cleanup = kvmd.extras.cleanup:main",
"kvmd-wscli = kvmd.extras.wscli:main",
- "kvmd-explorehw = kvmd.extras.explorehw:main",
],
},
diff --git a/os/platforms/v1/Dockerfile.part b/os/platforms/v1/Dockerfile.part
index c525b8e7..566f229c 100644
--- a/os/platforms/v1/Dockerfile.part
+++ b/os/platforms/v1/Dockerfile.part
@@ -4,7 +4,8 @@ RUN pkg-install \
nginx
COPY stages/pikvm/config.txt /boot/
-COPY stages/pikvm/99-pikvm.conf /etc/sysctl.d/
+COPY stages/pikvm/sysctl.conf /etc/sysctl.d/99-pikvm.conf
+COPY stages/pikvm/udev.rules /etc/udev/rules.d/pikvm.rules
COPY stages/pikvm/index.html /srv/http/
COPY stages/pikvm/kvmd.yaml /etc/
COPY stages/pikvm/nginx.conf /etc/nginx/
diff --git a/os/platforms/v1/kvmd.yaml b/os/platforms/v1/kvmd.yaml
index 3f2e8751..52890551 100644
--- a/os/platforms/v1/kvmd.yaml
+++ b/os/platforms/v1/kvmd.yaml
@@ -24,8 +24,7 @@ kvmd:
state_poll: 0.1
msd:
- # FIXME: It's for laptop lol
- bind: "1-2:1.0"
+ device: "/dev/kvmd-msd"
init_delay: 2.0
write_meta: true
chunk_size: 8192
@@ -46,7 +45,7 @@ kvmd:
cmd:
- "/usr/bin/mjpg_streamer"
- "-i"
- - "input_uvc.so -d /dev/video0 -e 2 -y -n -r {width}x{height}"
+ - "input_uvc.so -d /dev/kvmd-streamer -e 2 -y -n -r {width}x{height}"
- "-o"
- "output_http.so -l localhost -p 8082"
diff --git a/os/platforms/v1/99-pikvm.conf b/os/platforms/v1/sysctl.conf
index 71db0efc..71db0efc 100644
--- a/os/platforms/v1/99-pikvm.conf
+++ b/os/platforms/v1/sysctl.conf
diff --git a/os/platforms/v1/udev.rules b/os/platforms/v1/udev.rules
new file mode 100644
index 00000000..99cb0e45
--- /dev/null
+++ b/os/platforms/v1/udev.rules
@@ -0,0 +1,4 @@
+# https://unix.stackexchange.com/questions/66901/how-to-bind-usb-device-under-a-static-name
+# https://wiki.archlinux.org/index.php/Udev#Setting_static_device_names
+KERNEL=="video[0-9]*", SUBSYSTEM=="video4linux", KERNELS=="1-1.3:1.0", SYMLINK+="kvmd-streamer"
+KERNEL=="sd[a-z]", SUBSYSTEM=="block", KERNELS=="1-1.4:1.0", SYMLINK+="kvmd-msd"