mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2025-12-12 01:00:29 +08:00
297 lines
12 KiB
Diff
297 lines
12 KiB
Diff
diff -ruN kvmd/aiohelpers.py kvmd/aiohelpers.py
|
|
--- kvmd/aiohelpers.py 2023-01-30 03:25:23.556804000 +0700
|
|
+++ kvmd/aiohelpers.py 2023-01-30 08:12:21.773899000 +0700
|
|
@@ -38,11 +38,26 @@
|
|
]
|
|
logger.info("Remounting %s storage to %s: %s ...", name, mode.upper(), tools.cmdfmt(cmd))
|
|
try:
|
|
- proc = await aioproc.log_process(cmd, logger)
|
|
- if proc.returncode != 0:
|
|
- assert proc.returncode is not None
|
|
- raise subprocess.CalledProcessError(proc.returncode, cmd)
|
|
- except Exception as err:
|
|
- logger.error("Can't remount %s storage: %s", name, tools.efmt(err))
|
|
- return False
|
|
- return True
|
|
+ await _run_helper(cmd)
|
|
+ except Exception:
|
|
+ logger.error("Can't remount internal storage")
|
|
+ raise
|
|
+
|
|
+
|
|
+async def unlock_drive(base_cmd: list[str]) -> None:
|
|
+ logger = get_logger(0)
|
|
+ logger.info("Unlocking the drive ...")
|
|
+ try:
|
|
+ await _run_helper(base_cmd)
|
|
+ except Exception:
|
|
+ logger.error("Can't unlock the drive")
|
|
+ raise
|
|
+
|
|
+
|
|
+# =====
|
|
+async def _run_helper(cmd: list[str]) -> None:
|
|
+ logger = get_logger(0)
|
|
+ logger.info("Executing helper %s ...", cmd)
|
|
+ proc = await aioproc.log_process(cmd, logger)
|
|
+ if proc.returncode != 0:
|
|
+ logger.error(f"Error while helper execution: pid={proc.pid}; retcode={proc.returncode}")
|
|
diff -ruN kvmd/apps/otg/__init__.py kvmd/apps/otg/__init__.py
|
|
--- kvmd/apps/otg/__init__.py 2022-12-22 10:01:48.000000000 +0700
|
|
+++ kvmd/apps/otg/__init__.py 2023-01-30 03:51:51.331539000 +0700
|
|
@@ -182,7 +182,6 @@
|
|
_chown(join(func_path, "lun.0/cdrom"), user)
|
|
_chown(join(func_path, "lun.0/ro"), user)
|
|
_chown(join(func_path, "lun.0/file"), user)
|
|
- _chown(join(func_path, "lun.0/forced_eject"), user)
|
|
_symlink(func_path, join(self.__profile_path, func))
|
|
name = ("Mass Storage Drive" if self.__msd_instance == 0 else f"Extra Drive #{self.__msd_instance}")
|
|
self.__create_meta(func, name)
|
|
@@ -291,7 +290,7 @@
|
|
logger.info("Disabling gadget %r ...", config.otg.gadget)
|
|
_write(join(gadget_path, "UDC"), "\n")
|
|
|
|
- _unlink(join(gadget_path, "os_desc", usb.G_PROFILE_NAME), optional=True)
|
|
+ _unlink(join(gadget_path, "os_desc", usb.G_PROFILE_NAME), True)
|
|
|
|
profile_path = join(gadget_path, usb.G_PROFILE)
|
|
for func in os.listdir(profile_path):
|
|
diff -ruN kvmd/apps/otgmsd/__init__.py kvmd/apps/otgmsd/__init__.py
|
|
--- kvmd/apps/otgmsd/__init__.py 2022-12-22 10:01:48.000000000 +0700
|
|
+++ kvmd/apps/otgmsd/__init__.py 2023-01-30 04:35:09.702576000 +0700
|
|
@@ -21,8 +21,10 @@
|
|
|
|
|
|
import os
|
|
+import signal
|
|
import errno
|
|
import argparse
|
|
+import psutil
|
|
|
|
from ...validators.basic import valid_bool
|
|
from ...validators.basic import valid_int_f0
|
|
@@ -53,6 +55,21 @@
|
|
raise
|
|
|
|
|
|
+def _unlock() -> None:
|
|
+ # https://github.com/torvalds/linux/blob/3039fad/drivers/usb/gadget/function/f_mass_storage.c#L2924
|
|
+ found = False
|
|
+ for proc in psutil.process_iter():
|
|
+ attrs = proc.as_dict(attrs=["name", "exe", "pid"])
|
|
+ if attrs.get("name") == "file-storage" and not attrs.get("exe"):
|
|
+ try:
|
|
+ proc.send_signal(signal.SIGUSR1)
|
|
+ found = True
|
|
+ except Exception as err:
|
|
+ raise SystemExit(f"Can't send SIGUSR1 to MSD kernel thread with pid={attrs['pid']}: {err}")
|
|
+ if not found:
|
|
+ raise SystemExit("Can't find MSD kernel thread")
|
|
+
|
|
+
|
|
# =====
|
|
def main(argv: (list[str] | None)=None) -> None:
|
|
(parent_parser, argv, config) = init(
|
|
@@ -77,7 +94,7 @@
|
|
parser.add_argument("--eject", action="store_true",
|
|
help="Eject the image")
|
|
parser.add_argument("--unlock", action="store_true",
|
|
- help="Does nothing, just for backward compatibility")
|
|
+ help="Send SIGUSR1 to MSD kernel thread")
|
|
options = parser.parse_args(argv[1:])
|
|
|
|
if config.kvmd.msd.type != "otg":
|
|
@@ -87,8 +104,11 @@
|
|
set_param = (lambda param, value: _set_param(config.otg.gadget, options.instance, param, value))
|
|
get_param = (lambda param: _get_param(config.otg.gadget, options.instance, param))
|
|
|
|
+ if options.unlock:
|
|
+ _unlock()
|
|
+
|
|
if options.eject:
|
|
- set_param("forced_eject", "")
|
|
+ set_param("file", "")
|
|
|
|
if options.set_cdrom is not None:
|
|
set_param("cdrom", str(int(options.set_cdrom)))
|
|
diff -ruN kvmd/helpers/unlock/__init__.py kvmd/helpers/unlock/__init__.py
|
|
--- kvmd/helpers/unlock/__init__.py 1970-01-01 07:00:00.000000000 +0700
|
|
+++ kvmd/helpers/unlock/__init__.py 2023-01-30 04:04:07.000000000 +0700
|
|
@@ -0,0 +1,58 @@
|
|
+# ========================================================================== #
|
|
+# #
|
|
+# KVMD - The main PiKVM daemon. #
|
|
+# #
|
|
+# Copyright (C) 2018-2022 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 sys
|
|
+import signal
|
|
+
|
|
+import psutil
|
|
+
|
|
+
|
|
+# =====
|
|
+_PROCESS_NAME = "file-storage"
|
|
+
|
|
+
|
|
+# =====
|
|
+def _log(msg: str) -> None:
|
|
+ print(msg, file=sys.stderr)
|
|
+
|
|
+
|
|
+def _unlock() -> None:
|
|
+ # https://github.com/torvalds/linux/blob/3039fad/drivers/usb/gadget/function/f_mass_storage.c#L2924
|
|
+ found = False
|
|
+ for proc in psutil.process_iter():
|
|
+ attrs = proc.as_dict(attrs=["name", "exe", "pid"])
|
|
+ if attrs.get("name") == _PROCESS_NAME and not attrs.get("exe"):
|
|
+ _log(f"Sending SIGUSR1 to MSD {_PROCESS_NAME!r} kernel thread with pid={attrs['pid']} ...")
|
|
+ try:
|
|
+ proc.send_signal(signal.SIGUSR1)
|
|
+ found = True
|
|
+ except Exception as err:
|
|
+ raise SystemExit(f"Can't send SIGUSR1 to MSD kernel thread with pid={attrs['pid']}: {err}")
|
|
+ if not found:
|
|
+ raise SystemExit(f"Can't find MSD kernel thread {_PROCESS_NAME!r}")
|
|
+
|
|
+
|
|
+# =====
|
|
+def main() -> None:
|
|
+ if len(sys.argv) != 2 or sys.argv[1] != "unlock":
|
|
+ raise SystemExit(f"Usage: {sys.argv[0]} [unlock]")
|
|
+ _unlock()
|
|
diff -ruN kvmd/helpers/unlock/__main__.py kvmd/helpers/unlock/__main__.py
|
|
--- kvmd/helpers/unlock/__main__.py 1970-01-01 07:00:00.000000000 +0700
|
|
+++ kvmd/helpers/unlock/__main__.py 2023-01-30 04:04:07.000000000 +0700
|
|
@@ -0,0 +1,24 @@
|
|
+# ========================================================================== #
|
|
+# #
|
|
+# KVMD - The main PiKVM daemon. #
|
|
+# #
|
|
+# Copyright (C) 2018-2022 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 . import main
|
|
+main()
|
|
diff -ruN kvmd/plugins/msd/otg/drive.py kvmd/plugins/msd/otg/drive.py
|
|
--- kvmd/plugins/msd/otg/drive.py 2022-12-22 10:01:48.000000000 +0700
|
|
+++ kvmd/plugins/msd/otg/drive.py 2023-01-30 06:31:13.923959000 +0700
|
|
@@ -51,10 +51,7 @@
|
|
# =====
|
|
|
|
def set_image_path(self, path: str) -> None:
|
|
- if path:
|
|
- self.__set_param("file", path)
|
|
- else:
|
|
- self.__set_param("forced_eject", "")
|
|
+ self.__set_param("file", path)
|
|
|
|
def get_image_path(self) -> str:
|
|
return self.__get_param("file")
|
|
diff -ruN kvmd/plugins/msd/otg/__init__.py kvmd/plugins/msd/otg/__init__.py
|
|
--- kvmd/plugins/msd/otg/__init__.py 2023-02-02 09:42:28.021418683 +0700
|
|
+++ kvmd/plugins/msd/otg/__init__.py 2023-02-02 09:50:38.774955045 +0700
|
|
@@ -129,6 +129,7 @@
|
|
sync_chunk_size: int,
|
|
|
|
remount_cmd: list[str],
|
|
+ unlock_cmd: list[str],
|
|
|
|
initial: dict,
|
|
|
|
@@ -140,6 +141,7 @@
|
|
self.__sync_chunk_size = sync_chunk_size
|
|
|
|
self.__remount_cmd = remount_cmd
|
|
+ self.__unlock_cmd = unlock_cmd
|
|
|
|
self.__initial_image: str = initial["image"]
|
|
self.__initial_cdrom: bool = initial["cdrom"]
|
|
@@ -169,6 +171,11 @@
|
|
"/usr/bin/kvmd-helper-otgmsd-remount", "{mode}",
|
|
], type=valid_command),
|
|
|
|
+ "unlock_cmd": Option([
|
|
+ "/usr/bin/sudo", "--non-interactive",
|
|
+ "/usr/bin/kvmd-helper-otgmsd-unlock", "unlock",
|
|
+ ], type=valid_command),
|
|
+
|
|
"initial": {
|
|
"image": Option("", type=valid_printable_filename, if_empty=""),
|
|
"cdrom": Option(False, type=valid_bool),
|
|
@@ -230,6 +237,7 @@
|
|
async def reset(self) -> None:
|
|
async with self.__state.busy(check_online=False):
|
|
try:
|
|
+ await self.__unlock_drive()
|
|
self.__drive.set_image_path("")
|
|
self.__drive.set_cdrom_flag(False)
|
|
self.__drive.set_rw_flag(False)
|
|
@@ -286,7 +294,7 @@
|
|
raise MsdUnknownImageError()
|
|
|
|
assert self.__state.vd.image.in_storage
|
|
-
|
|
+ await self.__unlock_drive()
|
|
self.__drive.set_rw_flag(self.__state.vd.rw)
|
|
self.__drive.set_cdrom_flag(self.__state.vd.cdrom)
|
|
if self.__state.vd.rw:
|
|
@@ -294,6 +302,7 @@
|
|
self.__drive.set_image_path(self.__state.vd.image.path)
|
|
|
|
else:
|
|
+ await self.__unlock_drive()
|
|
self.__state_check_connected()
|
|
self.__drive.set_image_path("")
|
|
await self.__remount_rw(False, fatal=False)
|
|
@@ -499,6 +508,7 @@
|
|
if image.exists():
|
|
logger.info("Setting up initial image %r ...", self.__initial_image)
|
|
try:
|
|
+ await self.__unlock_drive()
|
|
self.__drive.set_rw_flag(False)
|
|
self.__drive.set_cdrom_flag(self.__initial_cdrom)
|
|
self.__drive.set_image_path(image.path)
|
|
@@ -531,5 +541,8 @@
|
|
|
|
async def __remount_rw(self, rw: bool, fatal: bool=True) -> None:
|
|
if not (await aiohelpers.remount("MSD", self.__remount_cmd, rw)):
|
|
- if fatal:
|
|
- raise MsdError("Can't execute remount helper")
|
|
+ pass
|
|
+ #raise MsdError("Can't execute remount helper")
|
|
+
|
|
+ async def __unlock_drive(self) -> None:
|
|
+ await aiohelpers.unlock_drive(self.__unlock_cmd)
|