diff options
author | Devaev Maxim <[email protected]> | 2019-09-24 00:03:31 +0300 |
---|---|---|
committer | Devaev Maxim <[email protected]> | 2019-09-24 00:03:31 +0300 |
commit | aee005787c1c1082e50224fc492409e49b60d389 (patch) | |
tree | e531c4a616df4ebde6c69988e5a7c1bc21bf28df | |
parent | 661828502e7f9e3b8afcdff8def9678937de97a9 (diff) |
preparing to otg
-rw-r--r-- | kvmd/apps/kvmd/server.py | 13 | ||||
-rw-r--r-- | kvmd/plugins/hid/serial.py | 2 | ||||
-rw-r--r-- | kvmd/plugins/msd/__init__.py | 14 | ||||
-rw-r--r-- | kvmd/plugins/msd/disabled.py | 9 | ||||
-rw-r--r-- | kvmd/plugins/msd/relay.py | 93 | ||||
-rw-r--r-- | kvmd/validators/kvm.py | 4 | ||||
-rw-r--r-- | testenv/tests/validators/test_kvm.py | 13 | ||||
-rw-r--r-- | web/kvm/index.html | 6 | ||||
-rw-r--r-- | web/share/js/kvm/msd.js | 41 |
9 files changed, 90 insertions, 105 deletions
diff --git a/kvmd/apps/kvmd/server.py b/kvmd/apps/kvmd/server.py index e3413683..311cb6fd 100644 --- a/kvmd/apps/kvmd/server.py +++ b/kvmd/apps/kvmd/server.py @@ -64,7 +64,6 @@ from ...validators.auth import valid_auth_token from ...validators.kvm import valid_atx_power_action from ...validators.kvm import valid_atx_button -from ...validators.kvm import valid_kvm_target from ...validators.kvm import valid_log_seek from ...validators.kvm import valid_stream_quality from ...validators.kvm import valid_stream_fps @@ -468,12 +467,12 @@ class Server: # pylint: disable=too-many-instance-attributes return _json(self.__msd.get_state()) @_exposed("POST", "/msd/connect") - async def __msd_connect_handler(self, request: aiohttp.web.Request) -> aiohttp.web.Response: - to = valid_kvm_target(request.query.get("to")) - return _json(await ({ - "kvm": self.__msd.connect_to_kvm, - "server": self.__msd.connect_to_server, - }[to])()) + async def __msd_connect_handler(self, _: aiohttp.web.Request) -> aiohttp.web.Response: + return _json(await self.__msd.connect()) + + @_exposed("POST", "/msd/disconnect") + async def __msd_disconnect_handler(self, _: aiohttp.web.Request) -> aiohttp.web.Response: + return _json(await self.__msd.disconnect()) @_exposed("POST", "/msd/write") async def __msd_write_handler(self, request: aiohttp.web.Request) -> aiohttp.web.Response: diff --git a/kvmd/plugins/hid/serial.py b/kvmd/plugins/hid/serial.py index 18930504..e72961ab 100644 --- a/kvmd/plugins/hid/serial.py +++ b/kvmd/plugins/hid/serial.py @@ -184,7 +184,7 @@ class Plugin(BaseHid, multiprocessing.Process): # pylint: disable=too-many-inst } def start(self) -> None: - get_logger().info("Starting HID daemon ...") + get_logger(0).info("Starting HID daemon ...") multiprocessing.Process.start(self) def get_state(self) -> Dict: diff --git a/kvmd/plugins/msd/__init__.py b/kvmd/plugins/msd/__init__.py index fa31e00b..d5aa3064 100644 --- a/kvmd/plugins/msd/__init__.py +++ b/kvmd/plugins/msd/__init__.py @@ -44,19 +44,19 @@ class MsdOfflineError(MsdOperationError): super().__init__("MSD is not found") -class MsdAlreadyOnServerError(MsdOperationError): +class MsdAlreadyConnectedError(MsdOperationError): def __init__(self) -> None: super().__init__("MSD is already connected to Server") -class MsdAlreadyOnKvmError(MsdOperationError): +class MsdAlreadyDisconnectedError(MsdOperationError): def __init__(self) -> None: - super().__init__("MSD is already connected to KVM") + super().__init__("MSD is already disconnected from Server") -class MsdNotOnKvmError(MsdOperationError): +class MsdConnectedError(MsdOperationError): def __init__(self) -> None: - super().__init__("MSD is not connected to KVM") + super().__init__("MSD connected to Server, but should not") class MsdIsBusyError(MsdOperationError): @@ -76,10 +76,10 @@ class BaseMsd(BasePlugin): async def cleanup(self) -> None: pass - async def connect_to_kvm(self) -> Dict: + async def connect(self) -> Dict: raise NotImplementedError - async def connect_to_server(self) -> Dict: + async def disconnect(self) -> Dict: raise NotImplementedError async def reset(self) -> None: diff --git a/kvmd/plugins/msd/disabled.py b/kvmd/plugins/msd/disabled.py index dab0f406..56ed10db 100644 --- a/kvmd/plugins/msd/disabled.py +++ b/kvmd/plugins/msd/disabled.py @@ -46,8 +46,9 @@ class Plugin(BaseMsd): "busy": False, "uploading": False, "written": False, - "info": None, - "connected_to": None, + "current": None, + "storage": None, + "connected": False, } async def poll_state(self) -> AsyncGenerator[Dict, None]: @@ -55,10 +56,10 @@ class Plugin(BaseMsd): yield self.get_state() await asyncio.sleep(60) - async def connect_to_kvm(self) -> Dict: + async def connect(self) -> Dict: raise MsdDisabledError() - async def connect_to_server(self) -> Dict: + async def disconnect(self) -> Dict: raise MsdDisabledError() async def reset(self) -> None: diff --git a/kvmd/plugins/msd/relay.py b/kvmd/plugins/msd/relay.py index e807c24b..39818e95 100644 --- a/kvmd/plugins/msd/relay.py +++ b/kvmd/plugins/msd/relay.py @@ -48,7 +48,6 @@ from ... import gpio from ...yamlconf import Option -from ...validators.basic import valid_bool from ...validators.basic import valid_number from ...validators.basic import valid_int_f1 from ...validators.basic import valid_float_f01 @@ -59,9 +58,9 @@ from ...validators.hw import valid_gpio_pin from . import MsdError from . import MsdOfflineError -from . import MsdAlreadyOnServerError -from . import MsdAlreadyOnKvmError -from . import MsdNotOnKvmError +from . import MsdAlreadyConnectedError +from . import MsdAlreadyDisconnectedError +from . import MsdConnectedError from . import MsdIsBusyError from . import BaseMsd @@ -77,8 +76,8 @@ class _ImageInfo: @dataclasses.dataclass(frozen=True) class _DeviceInfo: path: str - real: str size: int + free: int image: Optional[_ImageInfo] @@ -147,8 +146,8 @@ def _explore_device(device_path: str) -> _DeviceInfo: return _DeviceInfo( path=device_path, - real=os.path.realpath(device_path), size=size, + free=(size - image_info.size if image_info else size), image=image_info, ) @@ -171,7 +170,6 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes init_delay: float, init_retries: int, reset_delay: float, - write_meta: bool, chunk_size: int, ) -> None: @@ -182,7 +180,6 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes self.__init_delay = init_delay self.__init_retries = init_retries self.__reset_delay = reset_delay - self.__write_meta = write_meta self.__chunk_size = chunk_size self.__region = aioregion.AioExclusiveRegion(MsdIsBusyError) @@ -198,8 +195,6 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes logger.info("Using %r as MSD", self.__device_path) try: aiotools.run_sync(self.__load_device_info()) - if self.__write_meta: - logger.info("Enabled image metadata writing") except Exception as err: log = (logger.error if isinstance(err, MsdError) else logger.exception) log("MSD is offline: %s", err) @@ -214,20 +209,29 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes "init_delay": Option(1.0, type=valid_float_f01), "init_retries": Option(5, type=valid_int_f1), "reset_delay": Option(1.0, type=valid_float_f01), - "write_meta": Option(True, type=valid_bool), - "chunk_size": Option(65536, type=(lambda arg: valid_number(arg, min=1024))), + + "chunk_size": Option(65536, type=(lambda arg: valid_number(arg, min=1024))), } def get_state(self) -> Dict: - online = bool(self._device_info) + current: Optional[Dict] = None + storage: Optional[Dict] = None + if self._device_info: + storage = { + "size": self._device_info.size, + "free": self._device_info.free, + } + if self._device_info.image: + current = dataclasses.asdict(self._device_info.image) return { "enabled": True, - "online": online, + "online": bool(self._device_info), "busy": self.__region.is_busy(), "uploading": bool(self.__device_file), "written": self.__written, - "info": (dataclasses.asdict(self._device_info) if online else None), - "connected_to": (("kvm" if self.__on_kvm else "server") if online else None), + "current": current, + "storage": storage, + "connected": (not self.__on_kvm), } async def poll_state(self) -> AsyncGenerator[Dict, None]: @@ -242,24 +246,18 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes @_msd_working @aiotools.atomic - async def connect_to_kvm(self) -> Dict: + async def connect(self) -> Dict: notify = False state: Dict = {} try: with self.__region: - if self.__on_kvm: - raise MsdAlreadyOnKvmError() + if not self.__on_kvm: + raise MsdAlreadyConnectedError() notify = True - gpio.write(self.__target_pin, False) - try: - await self.__load_device_info() - except Exception: - if not self.__on_kvm: - gpio.write(self.__target_pin, True) - raise - self.__on_kvm = True - get_logger(0).info("MSD switched to KVM: %s", self._device_info) + gpio.write(self.__target_pin, True) + self.__on_kvm = False + get_logger(0).info("MSD switched to Server") state = self.get_state() return state @@ -269,18 +267,24 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes @_msd_working @aiotools.atomic - async def connect_to_server(self) -> Dict: + async def disconnect(self) -> Dict: notify = False state: Dict = {} try: with self.__region: - if not self.__on_kvm: - raise MsdAlreadyOnServerError() + if self.__on_kvm: + raise MsdAlreadyDisconnectedError() notify = True - gpio.write(self.__target_pin, True) - self.__on_kvm = False - get_logger(0).info("MSD switched to Server") + gpio.write(self.__target_pin, False) + try: + await self.__load_device_info() + except Exception: + if not self.__on_kvm: + gpio.write(self.__target_pin, True) + raise + self.__on_kvm = True + get_logger(0).info("MSD switched to KVM: %s", self._device_info) state = self.get_state() return state @@ -310,10 +314,8 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes try: gpio.write(self.__reset_pin, False) finally: - try: - await self.__state_queue.put(self.get_state()) - finally: - self.__region.exit() + self.__region.exit() + await self.__state_queue.put(self.get_state()) @_msd_working @aiotools.atomic @@ -322,7 +324,7 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes self.__region.enter() try: if not self.__on_kvm: - raise MsdNotOnKvmError() + raise MsdConnectedError() self.__device_file = await aiofiles.open(self._device_info.path, mode="w+b", buffering=0) self.__written = 0 return self @@ -339,13 +341,12 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes async def write_image_info(self, name: str, complete: bool) -> None: assert self.__device_file assert self._device_info - if self.__write_meta: - if self._device_info.size - self.__written > _IMAGE_INFO_SIZE: - await self.__device_file.seek(self._device_info.size - _IMAGE_INFO_SIZE) - await self.__write_to_device_file(_make_image_info_bytes(name, self.__written, complete)) - await self.__device_file.seek(0) - else: - get_logger().error("Can't write image info because device is full") + if self._device_info.size - self.__written > _IMAGE_INFO_SIZE: + await self.__device_file.seek(self._device_info.size - _IMAGE_INFO_SIZE) + await self.__write_to_device_file(_make_image_info_bytes(name, self.__written, complete)) + await self.__device_file.seek(0) + else: + get_logger().error("Can't write image info because device is full") @aiotools.atomic async def write_image_chunk(self, chunk: bytes) -> int: diff --git a/kvmd/validators/kvm.py b/kvmd/validators/kvm.py index 6cd12478..e99929af 100644 --- a/kvmd/validators/kvm.py +++ b/kvmd/validators/kvm.py @@ -38,10 +38,6 @@ def valid_atx_button(arg: Any) -> str: return check_string_in_list(arg, "ATX button", ["power", "power_long", "reset"]) -def valid_kvm_target(arg: Any) -> str: - return check_string_in_list(arg, "KVM target", ["kvm", "server"]) - - def valid_log_seek(arg: Any) -> int: return int(valid_number(arg, min=0, name="log seek")) diff --git a/testenv/tests/validators/test_kvm.py b/testenv/tests/validators/test_kvm.py index 920dcb10..fb223d6a 100644 --- a/testenv/tests/validators/test_kvm.py +++ b/testenv/tests/validators/test_kvm.py @@ -29,7 +29,6 @@ from kvmd.keymap import KEYMAP from kvmd.validators import ValidatorError from kvmd.validators.kvm import valid_atx_power_action from kvmd.validators.kvm import valid_atx_button -from kvmd.validators.kvm import valid_kvm_target from kvmd.validators.kvm import valid_log_seek from kvmd.validators.kvm import valid_stream_quality from kvmd.validators.kvm import valid_stream_fps @@ -64,18 +63,6 @@ def test_fail__valid_atx_button(arg: Any) -> None: # ===== [email protected]("arg", ["KVM ", "SERVER "]) -def test_ok__valid_kvm_target(arg: Any) -> None: - assert valid_kvm_target(arg) == arg.strip().lower() - - [email protected]("arg", ["test", "", None]) -def test_fail__valid_kvm_target(arg: Any) -> None: - with pytest.raises(ValidatorError): - print(valid_kvm_target(arg)) - - -# ===== @pytest.mark.parametrize("arg", ["0 ", 0, 1, 13]) def test_ok__valid_log_seek(arg: Any) -> None: value = valid_log_seek(arg) diff --git a/web/kvm/index.html b/web/kvm/index.html index a2b898f7..71e92548 100644 --- a/web/kvm/index.html +++ b/web/kvm/index.html @@ -221,7 +221,7 @@ <div id="msd-new-image" class="msd-message"> <table class="msd-info"> <tr> - <td>New name:</td> + <td>New image:</td> <td id="msd-new-image-name" class="msd-info-value"></td> </tr> <tr> @@ -239,8 +239,8 @@ </div> <div class="menu-item-content-buttons buttons-row"> - <button disabled data-force-hide-menu id="msd-switch-to-kvm-button" class="row50">• Switch drive to KVM</button> - <button disabled data-force-hide-menu id="msd-switch-to-server-button" class="row50">• Switch drive to Server</button> + <button disabled data-force-hide-menu id="msd-connect-button" class="row50">• Connect drive to Server</button> + <button disabled data-force-hide-menu id="msd-disconnect-button" class="row50">• Disconnect drive</button> </div> </div> </li> diff --git a/web/share/js/kvm/msd.js b/web/share/js/kvm/msd.js index 6fb5eee6..be1f5777 100644 --- a/web/share/js/kvm/msd.js +++ b/web/share/js/kvm/msd.js @@ -45,8 +45,8 @@ export function Msd() { tools.setOnClick($("msd-upload-new-image-button"), __clickUploadNewImageButton); tools.setOnClick($("msd-abort-uploading-button"), __clickAbortUploadingButton); - tools.setOnClick($("msd-switch-to-kvm-button"), () => __clickSwitchButton("kvm")); - tools.setOnClick($("msd-switch-to-server-button"), () => __clickSwitchButton("server")); + tools.setOnClick($("msd-connect-button"), () => __clickConnectButton(true)); + tools.setOnClick($("msd-disconnect-button"), () => __clickConnectButton(false)); tools.setOnClick($("msd-reset-button"), __clickResetButton); }; @@ -80,8 +80,9 @@ export function Msd() { $("msd-progress-value").style.width = "0%"; }; - var __clickSwitchButton = function(to) { - let http = tools.makeRequest("POST", "/api/msd/connect?to=" + to, function() { + var __clickConnectButton = function(connect) { + let action = (connect ? "connect" : "disconnect"); + let http = tools.makeRequest("POST", `/api/msd/${action}`, function() { if (http.readyState === 4) { if (http.status !== 200) { wm.error("Switch error:<br>", http.responseText); @@ -90,14 +91,14 @@ export function Msd() { __applyState(); }); __applyState(); - wm.switchDisabled($(`msd-switch-to-${to}-button`), true); + wm.switchDisabled($(`msd-${action}-button`), true); }; var __selectNewImageFile = function() { let el_input = $("msd-select-new-image-file"); let image_file = (el_input.files.length ? el_input.files[0] : null); - if (image_file && image_file.size > __state.info.size) { - wm.error("New image is too big for your Mass Storage Device.<br>Maximum:", __formatSize(__state.info.size)); + if (image_file && image_file.size > __state.storage.size) { + wm.error("New image is too big for your Mass Storage Device.<br>Maximum:", __formatSize(__state.storage.size)); el_input.value = ""; image_file = null; } @@ -131,7 +132,7 @@ export function Msd() { $("msd-reset-button").classList.add("feature-disabled"); } - if (__state.connected_to === "server") { + if (__state.connected) { $("msd-another-another-user-uploads").style.display = "none"; $("msd-led").className = "led-green"; $("msd-status").innerHTML = $("msd-led").title = "Connected to Server"; @@ -145,7 +146,7 @@ export function Msd() { $("msd-another-another-user-uploads").style.display = "none"; $("msd-led").className = "led-gray"; if (__state.online) { - $("msd-status").innerHTML = $("msd-led").title = "Connected to KVM"; + $("msd-status").innerHTML = $("msd-led").title = "Disconnected"; } else { $("msd-status").innerHTML = $("msd-led").title = "Unavailable"; } @@ -153,18 +154,18 @@ export function Msd() { $("msd-offline").style.display = (__state.online ? "none" : "block"); $("msd-current-image-broken").style.display = ( - __state.online && __state.info.image && - !__state.info.image.complete && !__state.uploading ? "block" : "none" + __state.online && __state.current && + !__state.current.complete && !__state.uploading ? "block" : "none" ); - $("msd-current-image-name").innerHTML = (__state.online && __state.info.image ? __state.info.image.name : "None"); - $("msd-current-image-size").innerHTML = (__state.online && __state.info.image ? __formatSize(__state.info.image.size) : "None"); - $("msd-storage-size").innerHTML = (__state.online ? __formatSize(__state.info.size) : "Unavailable"); + $("msd-current-image-name").innerHTML = (__state.online && __state.current ? __state.current.name : "None"); + $("msd-current-image-size").innerHTML = (__state.online && __state.current ? __formatSize(__state.current.size) : "None"); + $("msd-storage-size").innerHTML = (__state.online ? __formatSize(__state.storage.size) : "Unavailable"); - wm.switchDisabled($("msd-switch-to-kvm-button"), (!__state.online || __state.connected_to === "kvm" || __state.busy)); - wm.switchDisabled($("msd-switch-to-server-button"), (!__state.online || __state.connected_to === "server" || __state.busy)); - wm.switchDisabled($("msd-select-new-image-button"), (!__state.online || __state.connected_to !== "kvm" || __state.busy || __upload_http)); - wm.switchDisabled($("msd-upload-new-image-button"), (!__state.online || __state.connected_to !== "kvm" || __state.busy || !__image_file)); + wm.switchDisabled($("msd-connect-button"), (!__state.online || __state.connected || __state.busy)); + wm.switchDisabled($("msd-disconnect-button"), (!__state.online || !__state.connected || __state.busy)); + wm.switchDisabled($("msd-select-new-image-button"), (!__state.online || __state.connected || __state.busy || __upload_http)); + wm.switchDisabled($("msd-upload-new-image-button"), (!__state.online || __state.connected || __state.busy || !__image_file)); wm.switchDisabled($("msd-abort-uploading-button"), (!__state.online || !__upload_http)); wm.switchDisabled($("msd-reset-button"), (!__state.enabled || __state.busy)); @@ -185,8 +186,8 @@ export function Msd() { $("msd-current-image-size").innerHTML = ""; $("msd-storage-size").innerHTML = ""; - wm.switchDisabled($("msd-switch-to-kvm-button"), true); - wm.switchDisabled($("msd-switch-to-server-button"), true); + wm.switchDisabled($("msd-connect-button"), true); + wm.switchDisabled($("msd-disconnect-button"), true); wm.switchDisabled($("msd-select-new-image-button"), true); wm.switchDisabled($("msd-upload-new-image-button"), true); wm.switchDisabled($("msd-abort-uploading-button"), true); |